條件變數是什嗎?
是一種同步對象。
條件變數有什麼用?
用於複雜的、多線程的、多核的程式中,實現多個線程間同步任務。
條件變數與其它同步對象的區別?
與事件、互斥鎖、segment等同步對象相比,條件變數最大的不同在於”條件“二字,其它同步對象的同步”條件“是固定的,如事件的被激發,互斥鎖被釋放,而條件變數的"條件"是完全自訂的,比如你可以實現當”張三賺了5塊錢、李四在看電視、奧巴馬訪問馬爾它“時,條件變數完成同步。所以說條件變數可用於複雜的同步任務。
Windows下有沒有條件變數?
簡單的答案是:沒有,Windows API沒有提供條件變數對象,這就是本文會存在的原因和要解決的問題。
複雜點的答案是:
- 使用Windows Vista之後的版本(Vista之後的版本提供了native的條件變數對象;
- 從開源庫中抽取;
- 你可以自已實現;
方案1不現實,因為現階段你的客戶大多數還是使用windows xp/2003以下的版本,而且Vista賣的也並不好;方案2可以參考ace庫,不過太多條件宏和不相關代碼,難以抽取使用(你不可能為了一個同步變數,而扯進整個龐大的ace庫吧);方案3難度更大,必須要熟悉多線程編程,還要考慮很多變態的細節,我就是採用方案3 - 自已實現的,因為網上沒有現成的,不得已而為之!而你就不必重新造輪子,直接copy下面的代碼到你的項目裡就可以直接使用了(只要你的項目是C++的)。
實現代碼如下:
class my_mutex<br />{<br />public:<br />my_mutex (bool be_initial_owner = false)<br />{<br />mutex_ = CreateMutexA (NULL, be_initial_owner, NULL);<br />}<br />~my_mutex (void)<br />{<br />CloseHandle (mutex_);<br />}<br />public:<br />int acquire (void)<br />{<br />DWORD ret = WaitForSingleObject (mutex_, INFINITE);<br />return ret == WAIT_OBJECT_0 ? 0 : -1;<br />}<br />int release (void)<br />{<br />BOOL bret = ReleaseMutex (mutex_);<br />return bret ? 0 : -1;<br />}<br />HANDLE handle (void)<br />{<br />return mutex_;<br />}<br />protected:<br />HANDLE mutex_;<br />};<br />class my_semaphore<br />{<br />public:<br />my_semaphore (long init_count, long max_count = (std::numeric_limits<long>::max)())<br />{<br />assert (init_count >= 0 && max_count > 0 && init_count <= max_count);<br />sema_ = CreateSemaphoreA (NULL, init_count, max_count, NULL);<br />}<br />~my_semaphore (void)<br />{<br />CloseHandle (sema_);<br />}<br />public:<br />int post (long count = 1)<br />{<br />BOOL bret = ReleaseSemaphore (sema_, count, NULL);<br />return bret ? 0 : -1;<br />}<br />int wait (long timeout = -1)<br />{<br />DWORD ret = WaitForSingleObject (sema_, timeout);<br />return ret == WAIT_OBJECT_0 ? 0 : -1;<br />}<br />HANDLE handle (void)<br />{<br />return sema_;<br />}<br />protected:<br />HANDLE sema_;<br />};<br />template<typename MUTEX><br />class my_condition<br />{<br />public:<br />my_condition (MUTEX &m)<br />: mutex_ (m)<br />, waiters_ (0)<br />, sema_ (0)<br />{<br />}<br />~my_condition (void)<br />{<br />}<br />public:<br />/// Returns a reference to the underlying mutex_;<br />MUTEX &mutex (void)<br />{<br />return mutex_;<br />}<br />/// Signal one waiting thread.<br />int signal (void)<br />{<br />// must hold the external mutex before enter<br />if ( waiters_ > 0 )<br />sema_.post ();<br />return 0;<br />}<br />/// Signal *all* waiting threads.<br />int broadcast (void)<br />{<br />// must hold the external mutex before enter<br />if ( waiters_ > 0 )<br />sema_.post (waiters_);<br />return 0;<br />}<br />int wait (unsigned long wait_time = -1)<br />{<br />// must hold the external mutex before enter<br />int ret = 0;<br />waiters_++;<br />ret = SignalObjectAndWait (mutex_.handle (), sema_.handle (), wait_time, FALSE);<br />mutex_.acquire ();<br />waiters_ --;<br />return ret == WAIT_OBJECT_0 ? 0 : -1;<br />}<br />protected:<br />MUTEX &mutex_;<br />/// Number of waiting threads.<br />long waiters_;<br />/// Queue up threads waiting for the condition to become signaled.<br />my_semaphore sema_;<br />};<br />
以上代碼採用模板實現,變件變數類my_condition的模板參數是與條件變數配合使用的互斥量類型,為了方便直接使用,互斥量類型我也一併提供了: my_mutex。
代碼我已在項目中測試使用過,如果發現問題,歡迎各路高手批評指正。