Condition Variables

Condition variables are synchronization primitives that enable threads to wait until a particular condition occurs.

Condition variables are user-mode objects that cannot be shared across processes.

Condition variables enable threads to atomically release a lock and enter the sleeping state.

They can be used with critical sections or slim reader/writer (SRW) locks.

Condition variables support operations that "wake one" or "wake all" waiting threads.

After a thread is woken, it re-acquires the lock it released when the thread entered the sleeping state.

条件变量是能够在特殊条件满足前使线程处于等待状态的同步原语.

条件变量是不能被跨进程共享的用户模式下的同步对象.

条件变量能够使线程原子性释放一个锁同一时候进入sleep 状态. 条件变量和Critical Section Object一起使用.

条件变量支持wake one 或者wake all 等待的线程.

Windows Server 2003 and Windows XP:  Condition variables are not supported.

It is often convenient to use more than one condition variable with the same lock.

For example, an implementation of a reader/writer lock might use a single critical section but separate condition variables for readers and writers.

在同一个锁上面使用条件变量是很实用的.

比方:对于同一个临界区通过把读操作和写操作通过条件变量来分离能够实现读锁,写锁以及读写锁.

The following code implements a producer/consumer queue.

The queue is represented as a bounded circular buffer, and is protected by a critical section.

The code uses two condition variables: one used by producers (BufferNotFull) and one used by consumers (BufferNotEmpty).

The code calls the InitializeConditionVariable function to create the condition variables.

The consumer threads call the SleepConditionVariableCS function to wait for items to be added to the queue and

the WakeConditionVariable function to signal the producer that it is ready for more items.

The producer threads call SleepConditionVariableCS to wait for the consumer to remove items from the queue and

 WakeConditionVariable to signal the consumer that there are more items in the queue.

实现一个生产者/消费者队列.

队列是一个被Critical Section Object 保护的有界限圆形BUFFER.

通过调用InitializeConditionVariable()函数去创建一个条件变量.

消费者调用SleepConditionVariableCS()函数等待有物品被增加到队列中,通过WakeConditionVariable()函数通知生产者生产很多其它的物品.

生产者调用SleepConditionVariableCS()函数等待消费者把物品从队列中移除,通过WakeConditionVariable()函数来通知消费者去消费很多其它的物品.

測试代码:UsingConditionVariables.cpp

#include <windows.h>
#include <stdlib.h>
#include <stdio.h> #define BUFFER_SIZE 10
#define PRODUCER_SLEEP_TIME_MS 500
#define CONSUMER_SLEEP_TIME_MS 2000 LONG Buffer[BUFFER_SIZE];
LONG LastItemProduced;
ULONG QueueSize;
ULONG QueueStartOffset; ULONG TotalItemsProduced;
ULONG TotalItemsConsumed; CONDITION_VARIABLE BufferNotEmpty;
CONDITION_VARIABLE BufferNotFull;
CRITICAL_SECTION BufferLock; BOOL StopRequested; DWORD WINAPI ProducerThreadProc (PVOID p)
{
ULONG ProducerId = (ULONG)(ULONG_PTR)p; while (true)
{
// Produce a new item. Sleep (rand() % PRODUCER_SLEEP_TIME_MS);
//原子锁
ULONG Item = InterlockedIncrement (&LastItemProduced);
//进入临界区,其它线程不能訪问下面被保护的资源
EnterCriticalSection (&BufferLock);
//仅仅有当有界缓冲区满了之后,才通知消费者来消费资源,否则就一直生产物品
while (QueueSize == BUFFER_SIZE && StopRequested == FALSE)
{
// Buffer is full - sleep so consumers can get items.
SleepConditionVariableCS (&BufferNotFull, &BufferLock, INFINITE);
} if (StopRequested == TRUE)
{
LeaveCriticalSection (&BufferLock);
break;
} // Insert the item at the end of the queue and increment size. Buffer[(QueueStartOffset + QueueSize) % BUFFER_SIZE] = Item;
QueueSize++;
TotalItemsProduced++; printf ("Producer %u: item %2d, queue size %2u\r\n", ProducerId, Item, QueueSize);
//离开临界区,其它线程可訪问该临界区
LeaveCriticalSection (&BufferLock); // If a consumer is waiting, wake it. WakeConditionVariable (&BufferNotEmpty);
} printf ("Producer %u exiting\r\n", ProducerId);
return 0;
}
//消费者线程
DWORD WINAPI ConsumerThreadProc (PVOID p)
{
//消费数量
ULONG ConsumerId = (ULONG)(ULONG_PTR)p; while (true)
{ //临界区,当一个线程在获取临界区权利时,其它线程都要等待.
EnterCriticalSection (&BufferLock);
//当前缓存区为零
while (QueueSize == 0 && StopRequested == FALSE)
{
// Buffer is empty - sleep so producers can create items.
//通知生产者进行生产物品.当生产者完毕生产后,则通知消费者来消费
SleepConditionVariableCS (&BufferNotEmpty, &BufferLock, INFINITE);
} if (StopRequested == TRUE && QueueSize == 0)
{
LeaveCriticalSection (&BufferLock);
break;
} // Consume the first available item. LONG Item = Buffer[QueueStartOffset]; QueueSize--;
QueueStartOffset++;
TotalItemsConsumed++; if (QueueStartOffset == BUFFER_SIZE)
{
QueueStartOffset = 0;
} printf ("Consumer %u: item %2d, queue size %2u\r\n",
ConsumerId, Item, QueueSize); LeaveCriticalSection (&BufferLock); // If a producer is waiting, wake it. WakeConditionVariable (&BufferNotFull); // Simulate processing of the item. Sleep (rand() % CONSUMER_SLEEP_TIME_MS);
} printf ("Consumer %u exiting\r\n", ConsumerId);
return 0;
} int main ( void )
{ InitializeConditionVariable (&BufferNotEmpty);
InitializeConditionVariable (&BufferNotFull); InitializeCriticalSection (&BufferLock); DWORD id;
HANDLE hProducer1 = CreateThread (NULL, 0, ProducerThreadProc, (PVOID)1, 0, &id);
HANDLE hConsumer1 = CreateThread (NULL, 0, ConsumerThreadProc, (PVOID)1, 0, &id);
HANDLE hConsumer2 = CreateThread (NULL, 0, ConsumerThreadProc, (PVOID)2, 0, &id); puts ("Press enter to stop...");
getchar(); EnterCriticalSection (&BufferLock);
StopRequested = TRUE;
LeaveCriticalSection (&BufferLock); WakeAllConditionVariable (&BufferNotFull);
WakeAllConditionVariable (&BufferNotEmpty); WaitForSingleObject (hProducer1, INFINITE);
WaitForSingleObject (hConsumer1, INFINITE);
WaitForSingleObject (hConsumer2, INFINITE); printf ("TotalItemsProduced: %u, TotalItemsConsumed: %u\r\n",
TotalItemsProduced, TotalItemsConsumed);
return 0;
}

Condition Variables的更多相关文章

  1. 使用Condition Variables 实现一个线程安全队列

    使用Condition Variables实现一个线程安全队列 测试机: i7-4800MQ .7GHz, logical core, physical core, 8G memory, 256GB ...

  2. 深入解析条件变量(condition variables)

    深入解析条件变量 什么是条件变量(condition variables) 引用APUE中的一句话: Condition variables are another synchronization m ...

  3. 并行编程条件变量(posix condition variables)

    在整理Java LockSupport.park()东方的,我看到了"Spurious wakeup",通过重新梳理. 首先,可以在<UNIX级别编程环境>在样本: # ...

  4. [development][C] 条件变量(condition variables)的应用场景是什么

    产生这个问题的起因是这样的: ‎[:] ‎<‎tong‎>‎ lilydjwg: 主线程要启动N个子线程, 一个局部变量作为把同样的参数传入每一个子线程. 子线程在开始的十行会处理完参数. ...

  5. 4.锁--并行编程之条件变量(posix condition variables)

    在整理Java LockSupport.park()的东东.看到了个"Spurious wakeup".又一次梳理下. 首先来个<UNIX环境高级编程>里的样例: [c ...

  6. c++11多线程记录6:条件变量(condition variables)

    https://www.youtube.com/watch?v=13dFggo4t_I视频地址 实例1 考虑这样一个场景:存在一个全局队列deque,线程A向deque中推入数据(写),线程B从deq ...

  7. 第8章 用户模式下的线程同步(4)_条件变量(Condition Variable)

    8.6 条件变量(Condition Variables)——可利用临界区或SRWLock锁来实现 8.6.1 条件变量的使用 (1)条件变量机制就是为了简化 “生产者-消费者”问题而设计的一种线程同 ...

  8. java线程并发控制:ReentrantLock Condition使用详解

    本文摘自:http://outofmemory.cn/java/java.util.concurrent/lock-reentrantlock-condition java的java.util.con ...

  9. android分析之Condition

    Condition的含义是条件变量,其实现依赖于系统,一般都要配合Mutex使用,使用步骤为:给mutex上锁(Lock),调用wait等待"条件"发生,如果没有发生则re-wai ...

随机推荐

  1. 秒懂,Java 注解 (Annotation)你可以这样学

    转自: https://blog.csdn.net/briblue/article/details/73824058 文章开头先引入一处图片. 这处图片引自老罗的博客.为了避免不必要的麻烦,首先声明我 ...

  2. Cantor展开式

    X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! 其中,a为整数,并且0<=ai<i(1<=i<=n).这就是康托展开 ...

  3. Linux下的串口编程实例

    //串口相关的头文件  #include<stdio.h>      /*标准输入输出定义*/  #include<stdlib.h>     /*标准函数库定义*/  #in ...

  4. [leetcode]Distinct Subsequences @ Python

    原题地址:https://oj.leetcode.com/problems/distinct-subsequences/ 题意: Given a string S and a string T, co ...

  5. NodeJS之Mac初体验

    NodeJS之前在Window试用过一下,不过在mac上这种类Unix上属于第一次使用,JavaScript是脚本语言,脚本语言都需要一个解析器才能运行,通常我们在Html页面写的JS,浏览器充当了解 ...

  6. NSURLSession下载

    ios7引入了NSURLSession,通过它可以支持后台相关的网络操作的新特性: 1. 后台上传下载: 2.不需要通过nsoperation,直接用nsurlsession的api就可以做到网络操作 ...

  7. 实例游戏内存修改器----CUI版本模拟

    实现说明: 目标进程内存中很可能存在多个你要搜索的值, 所以在进行第一次搜索的时候, 要把搜索到的地址记录下来,然后让用户改变要搜索的值,再在记录的地址中搜索,直到搜索到的地址惟一为止.为此写两个辅助 ...

  8. IT痴汉的工作现状42-Android越用越慢?立场不同,谈何信任!

    大海和我一次闲聊中问,你做安卓这么久.能给我解释一下为什么安卓手机用半年后就变慢吗? 呃... 伟仔还真是头一次听说这么精准的半年就慢的说法. 大海继续说."能不能是厂家有益设置的?哦,也不 ...

  9. Vim 命令、操作、快捷键全集

    Vim是一个类似于Vi的著名的功能强大.高度可定制的文本编辑器,在Vi的基础上改进和增加了很多特性.Vim是自由软件. 命令历史 以:和/开头的命令都有历史纪录,可以首先键入:或/然后按上下箭头来选择 ...

  10. POI中setDefaultColumnWidth方法不起作用的原因

    sheet.setDefaultRowHeight((short) (2 * 256)); //设置默认行高,表示2个字符的高度 sheet.setDefaultColumnWidth(17);   ...