线程同步之条件变量
一、引言
假設有一個任務,由我和張三共同完成。張三把寄來的文稿初步審閱后放入一個隊列,我負責將這個隊列中的文稿進行審批,決定刊登與否。張三審閱一份文稿需要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的那些線程。
總結
 
                            
                        - 上一篇: IRP和IO_STACK_LOCATIO
- 下一篇: 为什么很少见工资高的程序员炫富?
