Condition Variables
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的更多相关文章
- 使用Condition Variables 实现一个线程安全队列
使用Condition Variables实现一个线程安全队列 测试机: i7-4800MQ .7GHz, logical core, physical core, 8G memory, 256GB ...
- 深入解析条件变量(condition variables)
深入解析条件变量 什么是条件变量(condition variables) 引用APUE中的一句话: Condition variables are another synchronization m ...
- 并行编程条件变量(posix condition variables)
在整理Java LockSupport.park()东方的,我看到了"Spurious wakeup",通过重新梳理. 首先,可以在<UNIX级别编程环境>在样本: # ...
- [development][C] 条件变量(condition variables)的应用场景是什么
产生这个问题的起因是这样的: [:] <tong> lilydjwg: 主线程要启动N个子线程, 一个局部变量作为把同样的参数传入每一个子线程. 子线程在开始的十行会处理完参数. ...
- 4.锁--并行编程之条件变量(posix condition variables)
在整理Java LockSupport.park()的东东.看到了个"Spurious wakeup".又一次梳理下. 首先来个<UNIX环境高级编程>里的样例: [c ...
- c++11多线程记录6:条件变量(condition variables)
https://www.youtube.com/watch?v=13dFggo4t_I视频地址 实例1 考虑这样一个场景:存在一个全局队列deque,线程A向deque中推入数据(写),线程B从deq ...
- 第8章 用户模式下的线程同步(4)_条件变量(Condition Variable)
8.6 条件变量(Condition Variables)——可利用临界区或SRWLock锁来实现 8.6.1 条件变量的使用 (1)条件变量机制就是为了简化 “生产者-消费者”问题而设计的一种线程同 ...
- java线程并发控制:ReentrantLock Condition使用详解
本文摘自:http://outofmemory.cn/java/java.util.concurrent/lock-reentrantlock-condition java的java.util.con ...
- android分析之Condition
Condition的含义是条件变量,其实现依赖于系统,一般都要配合Mutex使用,使用步骤为:给mutex上锁(Lock),调用wait等待"条件"发生,如果没有发生则re-wai ...
随机推荐
- cannot ignore cache if it is not cached [ArcGIS Catalog 10]
由于我把缓存重命名,重启地图服务,再Caching中不再显示地图缓存了,我直接创建新的地图缓存,没想到出现了: 不知道怎么回事. 只好,把缓存 重新改名成原来的名字,然后,删除缓存,再建立缓存.
- 奇怪吸引子---ChenCelikovsky
奇怪吸引子是混沌学的重要组成理论,用于演化过程的终极状态,具有如下特征:终极性.稳定性.吸引性.吸引子是一个数学概念,描写运动的收敛类型.它是指这样的一个集合,当时间趋于无穷大时,在任何一个有界集上出 ...
- 如何查看Isilon节点的硬件信息?
Isilon节点虽然是一个Linux,但是很多linux下常用的命令都没有,比如说看内存的.笔者经过试验,列出了一些可用的命令. 查看硬件状态 isi_hw_status 查看内存 sysctl hw ...
- 解决在非Activity中使用startActivity
错误提示信息: Caused by: android.util.AndroidRuntimeException: Calling startActivity() from outside of an ...
- WebView JS交互 addJavascriptInterface MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- 大数据开发实战:Hadoop数据仓库开发实战
1.Hadoop数据仓库架构设计 如上图. ODS(Operation Data Store)层:ODS层通常也被称为准备区(Staging area),它们是后续数据仓库层(即基于Kimball维度 ...
- thinkcmf 角色授权支持分类
ThinkCMF中的权限是以后台菜单为基础来进行设置的(menu table),即如果你需要一个自定义的权限,那么你需要在后台菜单里添加一项菜单,然后在角色管理里可以针对角色进行授权 而现在遇到一 ...
- Pandas DataFrame学习笔记
对一个DF r1 r2 r3 c1 c2 c3 选行: df['r1'] df['r2':'r2'] #包含r2 df[df['c1']>5] #按条件选 选列: df['c1'] ...
- [PureScript] Basic Data Constructors in PureScript
PureScript types are very extensive and we are going to experiment with type constructors and how to ...
- Android 八款开源 Android 游戏引擎
原文地址 本文内容 Angle Rokon LGame AndEngine libgdx jPCT Alien3d Catcake 最近无意间看到一篇关于 Android 搜索引擎的文章,于是搜索了, ...