我想问一下,是否可以使用1个条件变量与2个互斥锁关联,用于2种数据更新。
基本上,我有thread1和thread2。Thread1可以等待2种类型的数据更新,所以它有2个互斥锁,每个互斥锁一个。(我知道我可以使用一个互斥锁来处理所有这些数据,但这不是这个问题的重点,对吧?)我当然不希望它在data2已经可用的时候等待data1,所以它只有一个条件变量。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包围,所以如果cond_var在lock1上被唤醒,但data2可用,thread1将继续处理data2。
实际的实现是通过boost::thread实现的,因为我测试的平台是Linux,所以boost::thread应该通过pthread实现。
在我读过的几乎所有关于条件变量的教程和文档中,它只与一个互斥锁相关联。所以我很想知道上面的程序是可以使用的,还是有根本性的缺陷。
发布于 2012-10-18 17:50:46
这样就可以了。
Boost.Thread实现了C++11线程库(在v1.50之前它有一些差异,但现在非常接近),并且该线程库在概念上与Pthread模型很接近,但使用了不同的API,所以我们可以查看这些规范来找到答案。
C++11标准中的规则是:
要求:
lock.owns_lock()为true,lock.mutex()由调用线程锁定,并且
-没有其他线程正在等待此condition_variable对象或
- lock.mutex()为所有并发等待(via wait、wait_for或wait_until)线程提供的每个lock参数返回相同的值。
在本例中,互斥锁被正确锁定,并且只有一个线程在condvar上等待,因此满足了条件。
POSIX中的规则是等效的,但表达方式不同:
对同一条件变量的并发
pthread_cond_timedwait()或pthread_cond_wait()操作使用多个互斥锁的效果是不确定的;也就是说,当线程等待条件变量时,条件变量将绑定到唯一互斥锁,而这种(动态)绑定将在等待返回时结束。
同样,您没有并发的等待操作。
一般来说,只要不等待同时使用不同的互斥锁,就可以使用带有不同互斥锁的condvar。在等待condvar时,您将其与一个互斥锁和一个谓词(“条件”)相关联,因此,正如POSIX所描述的,condvar和互斥锁“绑定”在一起,任何一个condvar都不能同时绑定到多个互斥锁。原因是,当condvar从等待中唤醒时,它必须重新获取与其关联的互斥锁,如果不同的线程将其与不同的互斥锁一起使用,它可能会在错误的线程中重新锁定错误的互斥锁,从而导致混乱。一个线程会醒来,以为它已经重新锁定了等待它的互斥锁,但它实际上在另一个互斥锁上获得了一个锁,可能是一个它没有任何引用的互斥锁,因此永远不能解锁。死锁和/或不确定的行为,还有狮子、老虎和熊,哦,我的天。
在您的情况下,没有并发等待,所以没有问题。如果您有多个线程在等待,则需要确保两个线程在任何给定的等待中都使用相同的互斥...这将是困难的,因为您将需要一些额外的同步,所以只使用两个condvar会更简单。
https://stackoverflow.com/questions/12950540
复制相似问题