Linux学习之"使条件变量互斥量避免无限等待"

View Code
#include <iostream>
#include <unistd.h>
#include "CLThread.h"
#include "CLExecutiveFunctionProvider.h"
#include "CLMutex.h"
#include "CLCriticalSection.h"
#include "CLConditionVariable.h"

using namespace std;

struct SPara
{
CLConditionVariable condition;
CLMutex mutex;
volatile int flag;
};

class CLMyFunction : public CLExecutiveFunctionProvider
{
public:
CLMyFunction()
{
}

virtual ~CLMyFunction()
{
}

virtual CLStatus RunExecutiveFunction(void *pContext)
{
SPara *p = (SPara *)pContext;

{
CLCriticalSection cs(&(p->mutex));

p->flag = 1;
}

p->condition.Wakeup();

return CLStatus(0, 0);
}
};

int main()
{
SPara *p = new SPara;
p->flag = 0;

CLExecutiveFunctionProvider *myfunction = new CLMyFunction();
CLExecutive *pThread = new CLThread(myfunction);
pThread->Run((void *)p);

{
CLCriticalSection cs(&(p->mutex));

while(p->flag == 0)
p->condition.Wait(&(p->mutex));
}

pThread->WaitForDeath();

cout << "in main thread" << endl;

delete pThread;
delete myfunction;
delete p;

return 0;
}

这个程序理想顺序是主线程先进入临界区,然后执行p->condition.Wait(&(p->mutex))释放互斥锁并在条件变量上等待;接着子线程进入临界区把flag置1,而后退出临界区,最后唤醒主线程,使其继续运行。

主线程中,临界区为从”CLCriticalSection cs(&(p->mutex))“开始,到主线程被挂起为止;子线程中,临界区为从“CLCriticalSection cs(&(p->mutex))”到p->flag被赋值为1结束。

当主线程先进入临界区时,此时主线程已经被挂起,而子线程的唤醒尚未执行,故不会产生无限等待。

当子线程先进入临界区时,此时p->flag被置1,而主线程对p->flag的判断尚未执行,故主线程不会再等待条件变量。

等待线程的执行顺序:

  1. 调用pthread_mutex_lock
  2. While(判断条件)pthread_cond_wait(while判断等待条件是由于线程可能不是被pthread_cond_signal唤醒,可能是由信号等唤醒(futex)
  3. 调用pthread_mutex_unlock
被等待线程
  1. 调用pthread_mutex_lock
  2. 修改条件
  3. 调用pthread_mutex_unlock
  4. 调用pthread_mutex_broadcast

posted @ 2011-10-22 12:34  lq0729  阅读(735)  评论(0编辑  收藏  举报