標籤:
一、引言
假設有一個任務,由我和張三共同完成。張三把寄來的文稿初步審閱後放入一個隊列,我負責將這個隊列中的文稿進行審批,決定刊登與否。張三審閱一份文稿需要15分鐘,我處理一個文稿需要2分鐘。
如果將張三和我看作兩個線程,那麼我們共用一個隊列的資料。按照一般的多線程思路,他每隔一段時間往隊列中放入資料,我每隔一段時間檢查一下隊列中是否有資料,若有,則處理之。
若我們按照上面的方式工作,則大部分的時間,我只是在乾等著,所以,這是一種比較低效的方式。
但換一種方式之後,情況就好很多了。他每把一個文稿放入隊列,就檢查一下隊列中的文稿數量是否達到20,若達到,則通知我來處理。我來進行處理之後,由於我的處理速度更快,所以一段時間之後,隊列會變空,我便離開。這樣,我就可以把時間更有效率的利用起來,例如,利用空餘的時間打掃衛生、整理檔案或做一些其他的事情。
有些時候,我們不應讓一個線程“忙等”,而是應讓它休眠(sleep)以節省電腦資源,直到一個條件滿足之後,再繼續工作。
利用條件變數就可以達到上述目的。
條件變數有兩個狀態:成立和不成立。
二、初始化
在使用條件變數之前,需要定義一個CONDITION_VARIABLE類型的變數:
CONDITION_VARIABLE cv;
與條件變數有關的函數有5個;
InitializeConditionVariableSleepConditionVariableCSSleepConditionVariableSRWWakeConditionVariableWakeAllConditionVariable
對條件變數,不能在代碼中直接進行讀、寫,所有的操作必須通過上述函數進行。
條件變數在使用之前必須進行初始化,方法是:
InitializeConditionVariable(&cv);
在程式不再需要條件變數時,不需要手動銷毀它。
三、等待
等待條件變數可以用SleepConditionVariableCS或SleepConditionVariableSRW函數。
SleepConditionVariableCS(&cv, &cs, dwTimeout);
第一個參數是條件變數的指標,第二個參數是臨界區(CRITICAL_SECTION)指標,第三個參數是逾時,單位:毫秒。
這個函數的作用是,解鎖cs並等待cv成立,函數返回之後,會將cs重新鎖上,並將cs設為不成立。在等待期間,當前線程會休眠,直到它被喚醒(見後面介紹的用來喚醒的函數)。
SleepConditionVariableSRW用法與之類似,詳見這裡:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686304.aspx
四、通知(喚醒)
WakeConditionVariable(&cv);
用WakeConditionVariable將cv的狀態設為成立,並喚醒正在等待cv的那些線程中的一個。
WakeAllConditionVariable(&cv);
用WakeAllConditionVariable將cv的狀態設為成立,並喚醒所有的正在等待cv的那些線程。
Windows線程同步【5】條件變數(Condition Variable)