一、引言
假设有一个任务,由我和张三共同完成。张三把寄来的文稿初步审阅后放入一个队列,我负责将这个队列中的文稿进行审批,决定刊登与否。张三审阅一份文稿需要15分钟,我处理一个文稿需要2分钟。
如果将张三和我看作两个线程,那么我们共享一个队列的数据。按照一般的多线程思路,他每隔一段时间往队列中放入数据,我每隔一段时间检查一下队列中是否有数据,若有,则处理之。
若我们按照上面的方式工作,则大部分的时间,我只是在干等着,所以,这是一种比较低效的方式。
但换一种方式之后,情况就好很多了。他每把一个文稿放入队列,就检查一下队列中的文稿数量是否达到20,若达到,则通知我来处理。我来进行处理之后,由于我的处理速度更快,所以一段时间之后,队列会变空,我便离开。这样,我就可以把时间更有效率的利用起来,例如,利用空余的时间打扫卫生、整理文件或做一些其他的事情。
有些时候,我们不应让一个线程“忙等”,而是应让它休眠(sleep)以节省计算机资源,直到一个条件满足之后,再继续工作。
利用条件变量就可以达到上述目的。
条件变量有两个状态:成立和不成立。
二、初始化
在使用条件变量之前,需要定义一个CONDITION_VARIABLE类型的变量:
1
|
CONDITION_VARIABLE cv;
|
与条件变量有关的函数有5个;
1
2
3
4
5
|
InitializeConditionVariable
SleepConditionVariableCS
SleepConditionVariableSRW
WakeConditionVariable
WakeAllConditionVariable
|
对条件变量,不能在代码中直接进行读、写,所有的操作必须通过上述函数进行。
条件变量在使用之前必须进行初始化,方法是:
1
|
InitializeConditionVariable(&cv);
|
在程序不再需要条件变量时,不需要手动销毁它。
三、等待
等待条件变量可以用SleepConditionVariableCS或SleepConditionVariableSRW函数。
1
|
SleepConditionVariableCS(&cv, &cs, dwTimeout);
|
第一个参数是条件变量的指针,第二个参数是临界区(CRITICAL_SECTION)指针,第三个参数是超时,单位:毫秒。
这个函数的作用是,解锁cs并等待cv成立,函数返回之后,会将cs重新锁上,并将cs设为不成立。在等待期间,当前线程会休眠,直到它被唤醒(见后面介绍的用来唤醒的函数)。
SleepConditionVariableSRW用法与之类似,详见这里:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686304.aspx
四、通知(唤醒)
1
|
WakeConditionVariable(&cv);
|
用WakeConditionVariable将cv的状态设为成立,并唤醒正在等待cv的那些线程中的一个。
1
|
WakeAllConditionVariable(&cv);
|
用WakeAllConditionVariable将cv的状态设为成立,并唤醒所有的正在等待cv的那些线程。