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  版权声明:本文为博主原创文章,转载请附上博文连接!

相关文章
相关标签/搜索