工作积累之线程同步
来源:互联网 发布:java游戏高级编程 pdf 编辑:程序博客网 时间:2024/05/20 00:17
工作中需要在一个线程A中控制另外一个线程B的运行、暂停和取消暂停(继续运行)、停止,涉及到线程同步问题;以前需要线程同步时都是从网上找现成的代码,从未自己认真研究过其中的原理,今天就认真的总结一下。有关线程同步互斥的控制方法,可以参考上一篇文章,这里直接叙述实现的代码。
1. 首先是A线程如何控制B线程的运行:
下面的两段代码分别展示了如何使用互斥量来同步对变量m_bThreadRun的读写操作:
然后在A线程中创建B线程,并调用setThreadRunningFlag(true);代码:
setThreadRunningFlag( true );
AfxBeginThread( threadGrab, this );
再在B线程函数中循环调用threadFlag(),B线程就运行起来了,代码:
2.如何在A线程中控制B线程的暂停与取消暂停;
下面的两段代码分别展示了如何使用互斥量来同步对变量m_bPaused的读写操作:
初始时变量m_bPaused设为false;
m_bPaused = false;
然后在B线程函数中有如下代码:
因为m_bPaused=false,所以代码是无法执行到if语句中去的;一直在执行“计算处理”的代码;当在A线程中调用了PauseCapture函数时,
B线程的执行就会暂停下来,我们先看看PauseCapture函数的代码:
看到了吧,此时调用PauseCapture函数,会首先执行setGrabbingPausedFlag ( true );语句,把m_bPaused置为true;此时在B线程函数中就
可以进入if语句了;然后if语句中有WaitForSingleObject( m_heventUnpaused, INFINITE );这一行代码,大家还记得初始化时,
m_heventUnpaused被初始化成为了无信号状态,所以B线程就在这里无限期等待m_heventUnpaused变为有信号状态;B线程就暂停了;
当用户再次调用PauseCapture函数,会首先执行setGrabbingPausedFlag ( false );语句,把m_bPaused置为false;然后由于m_bPaused是
false,语句SetEvent( m_heventUnpaused );被调用,m_heventUnpaused就变为有信号状态了,然后B线程就可以继续往下执行了。
3.如何在A线程中控制B线程的停止;
调用函数StopCapture来停止B线程;
setThreadRunningFlag ( false );使得B线程函数中的while( threadFlag() )条件不成立,退出循环;
B线程函数:重点是最后一行代码;SetEvent( m_heventThreadDead );将m_heventThreadDead事件置为有信号状态;
然后在StopCapture函数中又调用了WaitForSingleObject( m_heventThreadDead, 5000 );ASSERT( dwRet == WAIT_OBJECT_0 );两条语句,
来确认B线程已经结束;
实现上述的同步,使用了两个事件(Event)和两个互斥量(Mutex),分别为:
/** Events 事件 */ HANDLE m_heventUnpaused; //暂停HANDLE m_heventThreadDead; //停止/** Mutexes 互斥量*/HANDLE m_hThreadRunningMutex; //运行HANDLE m_hGrabbingPauseFlagMutex; //暂停还有两个布尔变量,分别用来控制运行于暂停,是上面的两个互斥量保护的资源,如下:bool m_bPaused; //暂停bool m_bThreadRun; //运行先把上面各个变量初始化一下:
m_heventUnpaused = CreateEvent( NULL, FALSE, FALSE, NULL ); //将暂停事件初始化为无信号状态m_heventThreadDead = CreateEvent( NULL, FALSE, FALSE, NULL ); m_hThreadRunningMutex = ::CreateMutex( NULL, FALSE, NULL );m_hGrabbingPauseFlagMutex = ::CreateMutex( NULL, FALSE, NULL ); //将暂停互斥量初始化为无线程拥有该互斥量状态m_bPaused = false;m_bThreadRun = false;
1. 首先是A线程如何控制B线程的运行:
下面的两段代码分别展示了如何使用互斥量来同步对变量m_bThreadRun的读写操作:
BOOL threadFlag() //读操作{BOOL returnValue = false;DWORD dwRet = ::WaitForSingleObject( m_hThreadRunningMutex, 1000 );if( dwRet == WAIT_OBJECT_0 ){returnValue = m_bThreadRun;}::ReleaseMutex( m_hThreadRunningMutex );return returnValue;}; void setThreadRunningFlag( bool trueOrFalse ) //写操作{DWORD dwRet = ::WaitForSingleObject( m_hThreadRunningMutex, 5000 ); if( dwRet == WAIT_OBJECT_0 ){m_bThreadRun = trueOrFalse;}::ReleaseMutex( m_hThreadRunningMutex );return;};
然后在A线程中创建B线程,并调用setThreadRunningFlag(true);代码:
setThreadRunningFlag( true );
AfxBeginThread( threadGrab, this );
再在B线程函数中循环调用threadFlag(),B线程就运行起来了,代码:
UINT threadBFunction(void* pParam){ while( threadFlag() ) { ... } ...}
2.如何在A线程中控制B线程的暂停与取消暂停;
下面的两段代码分别展示了如何使用互斥量来同步对变量m_bPaused的读写操作:
BOOL grabbingPaused(){BOOL returnValue = false;DWORD dwRet = ::WaitForSingleObject( m_hGrabbingPauseFlagMutex, 5000 );if( dwRet == WAIT_OBJECT_0 ){returnValue = m_bPaused;}::ReleaseMutex( m_hGrabbingPauseFlagMutex );return returnValue;};void setGrabbingPausedFlag( bool trueOrFalse ){DWORD dwRet = ::WaitForSingleObject( m_hGrabbingPauseFlagMutex, 1000 );if( dwRet == WAIT_OBJECT_0 ){m_bPaused = trueOrFalse;}::ReleaseMutex( m_hGrabbingPauseFlagMutex );return;};
初始时变量m_bPaused设为false;
m_bPaused = false;
然后在B线程函数中有如下代码:
UINT threadBFunction(void* pParam){ while( threadFlag() ) { if( grabbingPaused() ) { DWORD dw = WaitForSingleObject( m_heventUnpaused, INFINITE ); ASSERT( dw == WAIT_OBJECT_0 ); } ... //计算处理 } ...}
因为m_bPaused=false,所以代码是无法执行到if语句中去的;一直在执行“计算处理”的代码;当在A线程中调用了PauseCapture函数时,
B线程的执行就会暂停下来,我们先看看PauseCapture函数的代码:
bool PauseCapture(){if ( grabbingPaused() ){setGrabbingPausedFlag ( false );}else{setGrabbingPausedFlag ( true );}if( !grabbingPaused() ){SetEvent( m_heventUnpaused ); }return true;}
看到了吧,此时调用PauseCapture函数,会首先执行setGrabbingPausedFlag ( true );语句,把m_bPaused置为true;此时在B线程函数中就
可以进入if语句了;然后if语句中有WaitForSingleObject( m_heventUnpaused, INFINITE );这一行代码,大家还记得初始化时,
m_heventUnpaused被初始化成为了无信号状态,所以B线程就在这里无限期等待m_heventUnpaused变为有信号状态;B线程就暂停了;
当用户再次调用PauseCapture函数,会首先执行setGrabbingPausedFlag ( false );语句,把m_bPaused置为false;然后由于m_bPaused是
false,语句SetEvent( m_heventUnpaused );被调用,m_heventUnpaused就变为有信号状态了,然后B线程就可以继续往下执行了。
3.如何在A线程中控制B线程的停止;
调用函数StopCapture来停止B线程;
bool StopCapture( void){// Inform the grab thread to quitif ( threadFlag() ){setThreadRunningFlag ( false );DWORD dwRet = WaitForSingleObject( m_heventThreadDead, 5000 );ASSERT( dwRet == WAIT_OBJECT_0 );}...}
setThreadRunningFlag ( false );使得B线程函数中的while( threadFlag() )条件不成立,退出循环;
B线程函数:重点是最后一行代码;SetEvent( m_heventThreadDead );将m_heventThreadDead事件置为有信号状态;
UINT threadBFunction(void* pParam){ while( threadFlag() ) { if( grabbingPaused() ) { DWORD dw = WaitForSingleObject( m_heventUnpaused, INFINITE ); ASSERT( dw == WAIT_OBJECT_0 ); } ... //计算处理 } SetEvent( m_heventThreadDead );}
然后在StopCapture函数中又调用了WaitForSingleObject( m_heventThreadDead, 5000 );ASSERT( dwRet == WAIT_OBJECT_0 );两条语句,
来确认B线程已经结束;
- 工作积累之线程同步
- 线程之线程同步
- 工作积累之CPPUNIT框架
- 工作积累之字节序
- 线程同步之信号量同步
- 线程同步之事件同步
- 线程同步之信号量同步
- Java线程之线程同步
- Java线程之线程同步
- java线程之线程同步
- Java线程之线程同步
- 线程同步之死锁
- POSIX线程之同步
- 线程同步之semaphore
- 线程同步之互斥量
- 线程同步之信号量
- 线程同步之Monitor
- 线程之同步
- jsp标签
- 使用eclipse快捷键提高开发效率
- 《第十二周任务一》理解基类中成员函数的访问限定符和派生类的继承方式
- TCP/IP 详解网络层
- Android 通过samples\android-x\BluetoothChat学习蓝牙操作
- 工作积累之线程同步
- 今天,昨天,三天前计算
- 禁止和启用约束
- VBA中变量和常量的命名规则
- error: 'UINT64_C' was not declared in this scope
- 第十二周实验报告1(修改)
- Windows Phone开发之发送邮件操作类
- 《Windows程序设计》对话框1
- poj 1995 整数快速幂模m