是否可以使用与2个互斥量相关的1个条件变量(单独)

时间:2012-10-18 08:44:20

标签: c++ mutex condition-variable

我想问一下,使用1个与2个互斥量相关的条件变量是否可以进行2种数据更新。

基本上,我有thread1和thread2。 Thread1可以等待2种数据更新,因此它有2个互斥,每个一个。 (我知道我可以使用一个互斥量用于所有这些数据,但这不是这个问题的重点,对吧?)我当然不希望它等待data1而data2已经可用,所以它只有1个条件变量。而thread2将提供data1和data2。问题是在thread2中,我不知道thread1现在是在等待data1还是data2,或者根本不在等待。

伪代码如下所示:

global data:
    cond_var
    mutex1
    data1
    mutex2
    data2

thread1:
    while true
        lock1.lock(mutex1)
        if data1 is not available
        cond_var.wait(lock1)
        if data1 is available
            process data1
        lock1.unlock()

        lock2.lock(mutex2)
        if data2 is not available
            cond_var.wait(lock2)
        if data2 is available
            process data2
        lock2.unlock()

thread2:
    func1:
        lock1.lock(mutex1)
        update data1
        cond_var.notify_all()
        lock1.unlock()

    func2:
        lock2.lock(mutex2)
        update data2
        cond_var.notify_all()
        lock2.unlock()

外界将调用func1或func2来更新数据。 当调用func1或func2时,它将发出cond_var信号,无论是在lock1还是lock2中。 cond_var的等待不会被while包围,所以如果在lock1上唤醒cond_var但data2可用,则thread1将继续处理data2。

实际的实现是通过boost :: thread,因为我的测试平台是Linux,所以boost :: thread应该通过pthread实现。

在几乎所有关于条件变量的教程和文档中,它只与1个互斥量相关联。所以我很想知道上面的程序是否可以使用,或者是否存在根本缺陷。

1 个答案:

答案 0 :(得分:1)

没关系。

Boost.Thread实现了C ++ 11线程库(它在v1.50之前有一些差异但现在非常接近)并且该线程库在概念上接近Pthread模型,但是使用不同的API,所以我们可以看看这些规格的答案。

C ++ 11标准中的规则是:

  

要求: lock.owns_lock()truelock.mutex()被调用线程锁定,并且     - 没有其他线程正在等待此condition_variable对象或
    - lock.mutex()为所有并发等待(lockvia waitwait_for个线程提供的每个wait_until参数返回相同的值。

在您的情况下,互斥锁被正确锁定,并且只有一个线程在condvar上等待,因此满足条件。

POSIX中的规则是等效的,但措辞不同:

  

在同一条件变量上使用多个互斥锁对并发pthread_cond_timedwait()pthread_cond_wait()运算的影响未定义;也就是说,当一个线程等待条件变量时,一个条件变量被绑定到一个唯一的互斥锁,并且这个(动态)绑定将在等待返回时结束。

同样,您没有并发等待操作。

通常,只要您不等待同时使用不同的互斥锁 ,就可以使用带有不同互斥锁的condvar。在等待condvar时,你将它与互斥锁和谓词(“条件”)相关联,所以当POSIX描述时,condvar和互斥锁被“绑定”在一起,并且任何condvar一次不能绑定到多个互斥锁。原因是当一个condvar从等待中唤醒时它必须重新获取它所关联的互斥锁,如果不同的线程使用它与不同的互斥锁,它可能会在错误的线程中重新锁定错误的互斥锁,从而导致混乱。一个线程会觉得它已经重新锁定了它等待的互斥锁,但它实际上锁定了一个不同的互斥锁,也许它没有任何引用,所以永远无法解锁。死锁和/或未定义的行为和狮子,老虎和熊,哦,我的。

在你的情况下没有并发等待,所以没问题。如果您有多个线程在等待,则需要确保两个线程都使用相同的互斥锁进行任何给定的等待...这将是困难的,因为您需要一些额外的同步,因此使用它会更简单两个condvars。