3

我会先介绍一些代码,因为解释更容易。假设互斥正确使用条件变量来保持它的简单:条件变量 - 等待/通知竞争条件

// Thread 1 
while(1) 
{ 
    conditionVariable.wait(); 
    // Do some work 
} 

// Thread 2 
while(1) 
{ 
    // Do some work 
    conditionVariable.notify_one(); 
} 

// Thread 3 
while(1) 
{ 
    // Do some work 
    conditionVariable.notify_one(); 
} 

我想实现的是,线程1是保证在条件变量上等待时,线程2或3螺纹通知。如代码所示,notify_one()wait()之间有很大的差距,以其他代码的形式标注评论。这个差距意味着有时notify_one()被调用之前有机会致电wait()

经过一番思考,似乎最接近我的是在notify_one()之前和wait()之前(在线程1的循环开始之前)使用某种形式的互斥。但是,无论如何完成,互斥和wait()之间仍然存在一小段差距(1行代码),允许线程2和3在线程1调用wait()之前调用notify_one()。这是不可能的,但可能的。

我也考虑过使用wait()谓词来标记一个允许其他线程通知的布尔值。我猜这会起作用,因为wait()是原子,但我想知道是否有更好的方法。也许我错误地接近了这一点。

总结:如何确保线程1在允许线程2和3通知之前等待?

回答

4

简而言之:考虑条件变量作为一种方法来通知其他线程某些变化,而不仅仅是一个信号。

为了做到这一点,条件变量应该伴随一个可以由接收线程处理的条件(简单的例子:一个整数递增)。

现在,为了解决您的问题,线程1可以使用一个条件变量伴随一个就绪布尔值来在其他线程准备好接收条件变量信号时发出信号,但是您最好先检查原始条件变量是否可以按照此处所述使用。基于问题(还需要conditionVariable的适当锁定)

伪代码:

// Thread 1 
while(1) 
{ 
    lockReady(); 
    ready = true; 
    unlockReady(); 
    readyCV.notify_one(); 
    conditionVariable.wait(); 

    // Do some work 
} 

// Thread 2 
while(1) 
{ 
    lockReady(); 
    while (! ready) readyCV.wait(); 
    ready = false; 
    unlockReady(); 
    // Do some work 
    conditionVariable.notify_one(); 
} 

// Thread 3 
while(1) 
{ 
    lockReady(); 
    while (! ready) readyCV.wait(); 
    ready = false; 
    unlockReady(); 
    // Do some work 
    conditionVariable.notify_one(); 
} 

也看到my previous answer