Windows下條件變量的實現

條件變量是什麼?編程

是一種同步對象。windows

 

條件變量有什麼用?多線程

用於複雜的、多線程的、多核的程序中,實現多個線程間同步任務。函數

 

條件變量與其它同步對象的區別?post

與事件、互斥鎖、segment等同步對象相比,條件變量最大的不一樣在於」條件「二字,其它同步對象的同步」條件「是固定的,如事件的被激發,互斥鎖被釋放,而條件變量的"條件"是徹底自定義的,好比你能夠實現當」張三賺了5塊錢、李四在看電視、奧巴馬訪問馬爾它「時,條件變量完成同步。因此說條件變量可用於複雜的同步任務。測試

 

Windows下有沒有條件變量?ui

簡單的答案是:沒有,Windows API沒有提供條件變量對象,這就是本文會存在的緣由和要解決的問題。atom

複雜點的答案是:.net

使用Windows Vista以後的版本(Vista以後的版本提供了native的條件變量對象;
從開源庫中抽取;
你能夠自已實現;
 線程

方案1不現實,由於現階段你的客戶大多數仍是使用windows xp/2003如下的版本,並且Vista賣的也並很差;
方案2能夠參考ace庫,不過太多條件宏和不相關代碼,難以抽取使用(你不可能爲了一個同步變量,而扯進整個龐大的ace庫吧);
方案3難度更大,必需要熟悉多線程編程,還要考慮不少變態的細節;

我就是採用方案3 -- 自已實現的。由於網上沒有現成的,不得已而爲之!而你就沒必要從新造輪子,直接copy下面的代碼到你的項目裏就能夠直接使用了(只要你的項目是C++的)。
 

實現代碼以下: 

class my_mutex
{
public:
    my_mutex (bool be_initial_owner = false)
    {
        mutex_ = CreateMutexA (NULL, be_initial_owner, NULL);
    }
 
    ~my_mutex (void)
    {
        CloseHandle (mutex_);
    }
 
public:
    int acquire (void)
    {
        DWORD ret = WaitForSingleObject (mutex_, INFINITE);
        return ret == WAIT_OBJECT_0 ? 0 : -1;
    }
 
    int release (void)
    {
        BOOL bret = ReleaseMutex (mutex_);
        return bret ? 0 : -1;
    }
 
    HANDLE handle (void)
    {
        return mutex_;
    }
 
protected:
    HANDLE mutex_;
};
 
class my_semaphore
{
public:
    my_semaphore (long init_count, long max_count = (std::numeric_limits<long>::max)())
    {
        assert (init_count >= 0 && max_count > 0 && init_count <= max_count);
        sema_ = CreateSemaphoreA (NULL, init_count, max_count, NULL);
    }
 
    ~my_semaphore (void)
    {
        CloseHandle (sema_);
    }
 
public:
    int post (long count = 1)
    {
        BOOL bret = ReleaseSemaphore (sema_, count, NULL);
        return bret ? 0 : -1;
    }
 
    int wait (long timeout = -1)
    {
        DWORD ret = WaitForSingleObject (sema_, timeout);
        return ret == WAIT_OBJECT_0 ? 0 : -1;
    }
 
    HANDLE handle (void)
    {
        return sema_;
    }
 
protected:
    HANDLE sema_;
};
 
template<typename MUTEX>
class my_condition
{
public:
    my_condition (MUTEX &m) 
        : mutex_ (m), waiters_ (0), sema_ (0)
    {}
 
    ~my_condition (void)
    {}
 
public:
    /// Returns a reference to the underlying mutex_;
    MUTEX &mutex (void)
    {
        return mutex_;
    }
 
    /// Signal one waiting thread.
    int signal (void)
    {
        // must hold the external mutex before enter
        if ( waiters_ > 0 )
            sema_.post ();
        return 0;
    }
 
    /// Signal *all* waiting threads.
    int broadcast (void)
    {
        // must hold the external mutex before enter
        if ( waiters_ > 0 )
            sema_.post (waiters_);
        return 0;
    }
 
    int wait (unsigned long wait_time = -1)
    {
        // must hold the external mutex before enter
        int ret = 0;
        waiters_++;
        ret = SignalObjectAndWait (mutex_.handle (), sema_.handle (), wait_time, FALSE);
        mutex_.acquire ();
        waiters_ --;
        return ret == WAIT_OBJECT_0 ? 0 : -1;
    }
 
protected:
    MUTEX &mutex_;
    /// Number of waiting threads.
    long waiters_;
    /// Queue up threads waiting for the condition to become signaled.
    my_semaphore sema_;
}; 
使用條件變量的示例:

/// 公共部分
// my_mutx m;
// my_condition c (m);
 
/// 消費者
m.acquire();
while (!condition_is_satisfied())
{
    c.wait(300);
}
handle_something();
m.release();
 
/// 生產者
produce_something();
m.acquire();
c.signal();
m.release();


    以上代碼採用模板實現,變件變量類my_condition的模板參數是與條件變量配合使用的互斥量類型,爲了方便直接使用,互斥量類型我也一併提供了: my_mutex。

 

    代碼我已在項目中測試使用過,若是發現問題,歡迎各路高手批評指正。

2018.6.11新增:

根據MSDN文檔對SignalObjectAndWait函數的描述,本文描述的代碼存在死鎖的風險:條件知足的信號通知丟失。解決的方法就是在調用my_condition的wait方法時,必定要加上比較短的超時參數(好比300毫秒或者幾秒,根據實際狀況調整),循環檢測以從新發現條件已經知足了(條件不會丟失,保存在信號量裏)。MSDN原文以下:

Note that the "signal" and "wait" are not guaranteed to be performed as an atomic operation. Threads executing on other processors can observe the signaled state of the first object before the thread calling SignalObjectAndWait begins its wait on the second object. ---------------------  做者:leafarmy  來源:CSDN  原文:https://blog.csdn.net/leafarmy/article/details/4039548  版權聲明:本文爲博主原創文章,轉載請附上博文連接!

相關文章
相關標籤/搜索