首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >是否可以使用与2个互斥锁关联的1个条件变量(单独使用)

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

Stack Overflow用户
提问于 2012-10-18 16:44:20
回答 1查看 214关注 0票数 3

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

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

伪代码将如下所示:

代码语言:javascript
运行
复制
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实现。

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-10-18 17:50:46

这样就可以了。

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

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

要求:lock.owns_lock()truelock.mutex()由调用线程锁定,并且

-没有其他线程正在等待此condition_variable对象或

- lock.mutex()为所有并发等待(via waitwait_forwait_until)线程提供的每个lock参数返回相同的值。

在本例中,互斥锁被正确锁定,并且只有一个线程在condvar上等待,因此满足了条件。

POSIX中的规则是等效的,但表达方式不同:

对同一条件变量的并发pthread_cond_timedwait()pthread_cond_wait()操作使用多个互斥锁的效果是不确定的;也就是说,当线程等待条件变量时,条件变量将绑定到唯一互斥锁,而这种(动态)绑定将在等待返回时结束。

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

一般来说,只要不等待同时使用不同的互斥锁,就可以使用带有不同互斥锁的condvar。在等待condvar时,您将其与一个互斥锁和一个谓词(“条件”)相关联,因此,正如POSIX所描述的,condvar和互斥锁“绑定”在一起,任何一个condvar都不能同时绑定到多个互斥锁。原因是,当condvar从等待中唤醒时,它必须重新获取与其关联的互斥锁,如果不同的线程将其与不同的互斥锁一起使用,它可能会在错误的线程中重新锁定错误的互斥锁,从而导致混乱。一个线程会醒来,以为它已经重新锁定了等待它的互斥锁,但它实际上在另一个互斥锁上获得了一个锁,可能是一个它没有任何引用的互斥锁,因此永远不能解锁。死锁和/或不确定的行为,还有狮子、老虎和熊,哦,我的天。

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12950540

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档