Condition Variables

原创 2015年07月09日 14:00:55

 

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;
}


 

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

在整理Java LockSupport.park()的东东,看到了个"Spurious wakeup",重新梳理下。 首先来个《UNIX环境高级编程》里的例子: #include struct ms...
  • hengyunabc
  • hengyunabc
  • 2014年06月02日 00:24
  • 4225

condition variables

1. 相关函数                                                                                            ...
  • linux_wgl
  • linux_wgl
  • 2011年11月21日 16:32
  • 368

c++11线程之条件变量condition_variable(二)

题目:编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。 采用C++11实现: ...
  • jiangheng0535
  • jiangheng0535
  • 2014年08月21日 16:00
  • 827

Condition Variables JAVA多线程

线程这方面的学习一直不是很充分,今天在看张孝祥的视频的时候看到了一个3个线程轮流工作的例子,有一定的难度,最后运用了condition较方便的实现了。于是又搜索了一下相关资料,汇总如下: Condit...
  • frone
  • frone
  • 2009年12月17日 18:13
  • 980

Using Condition Variables

原文地址:http://docs.oracle.com/cd/E19455-01/806-5257/6je9h032r/index.html Using Condition Variables Th...
  • kartorz
  • kartorz
  • 2014年02月20日 13:48
  • 978

mutex and Condition Variables

ref: http://blog.csdn.net/locape/article/details/6040383 http://blog.chinaunix.net/space.php?uid=23...
  • voider2008
  • voider2008
  • 2011年10月09日 09:46
  • 228

转:条件变量(Condition Variables)

条件变量(Condition Variables)条件变量是什么?条件变量为我们提供了另一种线程间同步的方法,然而,互斥量是通过控制线程访问数据来实现同步,条件变量允许线程同步是基于实际数据的值。 如...
  • yulanarti
  • yulanarti
  • 2011年02月21日 09:55
  • 4546

nachos-java Task1.2 Condition Variables

Task 1.2 Condition Variables 实验要求 实验关键代码 实验测试代码 关键代码分析 测试结果分析 实验要求◆ Implement condition variables di...
  • deep_kang
  • deep_kang
  • 2017年02月28日 21:12
  • 438

Condition Variables 条件变量

pthread_cond_wait(pthread_cond_t *, pthread_mutex *) 等待一个条件变量,并且释放传入的mutex锁 标准的用法就是 pthread_mutex...
  • qq_38255689
  • qq_38255689
  • 2017年11月21日 14:01
  • 54

Lock, semaphore, condition variables and monitors.

Semaphore:     Down operation on a semaphore checks to see if the value is greater than 0, if so, it...
  • fantasy666666
  • fantasy666666
  • 2015年03月16日 15:55
  • 544
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Condition Variables
举报原因:
原因补充:

(最多只允许输入30个字)