条件变量的用法:CONDITION_VARIABLE

条件变量的用法:CONDITION_VARIABLE  

2011-07-01 16:32:12|  分类: 默认分类 |举报 |字号 订阅

摘自:http://www.cnblogs.com/panda_lin/articles/1449139.html



多线程不仅仅是背几个API就能解决问题了

(英文版:http://msdn.microsoft.com/en-us/magazine/cc163405.aspx)介绍了Vista新增的同步原语,在讲到一下两段例子代码的时候有这么一段解释:

http://msdn.microsoft.com/zh-cn/magazine/cc163405.aspx

条件变量的用法:CONDITION_VARIABLE - honesthu - 我的博客 生产者
for (unsigned int i = 0;i < g_uiIterations;i++)
{
    EnterCriticalSection(
&g_csLock);

    
// Produce work
    g_listWork.push_back(i);

    LeaveCriticalSection(
&g_csLock);

    WakeConditionVariable(
&g_condNotEmpty);

    Sleep(g_uiProducerDelay);
}

 

条件变量的用法:CONDITION_VARIABLE - honesthu - 我的博客 消费者
while (true)
{
    EnterCriticalSection(
&g_csLock);

    
while (g_listWork.empty())
    {
        SleepConditionVariableCS(
&g_condNotEmpty,&g_csLock,INFINITE);
    }

    i 
= g_listWork.front();
    g_listWork.pop_front();

    LeaveCriticalSection(
&g_csLock);

    wcout 
<< L"Thread " << iThread << L" Consumed: " << i << endl;
    Sleep(g_uiConsumerDelay); 
// Simulating work
}

 

当得到条件变量信号时,该线程醒来并在 SleepConditionVariableCS 函数返回之前再次自动锁定关键节。使用者线程然后往回循环,并再次查看队列是否为空。当线程被释放后,再次检测状态非常重要,因为其状态可能在使用者被释 放之前已被另一个线程更改;另外,条件变量还可能被骗醒 (spurious wakeup),这样它可能会在条件发生变化之前运行。

对于骗醒我一开始怎么也没想明白,SleepConditionVariableCS明明是个阻塞调用,在条件变量被唤醒之前是不可能进入临界区的,既然如此,用if等不就可以了吗?自己写了一段code调试后证明,这种思维不是多线程的。看以下例子:

1、队列已空,生产者线程A在push了一个元素后离开临界区,在调用WakeConditionVariable前被消费者线程B抢占。

2、消费者线程B检测到g_listWork不为空,消费掉1个元素后离开,同时消费者线程C继续抢占CPU资源。

3、消费者线程C检测到g_listWork为空,调用SleepConditionVariableCS等待条件变量,此时生产者线程A获得CPU资源并唤醒条件变量。

4、消费者线程C从SleepConditionVariableCS返回,注意,这时的g_listWork是空的,如果不用while循环检测,就真的是被骗醒了~~~

所以多线程编程不仅仅是掌握几个API,重要的是能具体情况具体分析,仔细考虑各种竞争条件并加以合理规划。当然,能避免多线程就尽量避免,另 外,VS2010在多线程方面增加了很多特性,无论是managed还是native编程,如果你要求不太高的话,多线程库会帮你做很多事情,看了演示后 还是很期待的。

你可能感兴趣的:(多线程)