【问题标题】:Condition Variable - Wait/Notify Race Condition条件变量 - 等待/通知竞态条件
【发布时间】:2014-01-23 09:39:46
【问题描述】:

我将首先展示一些代码,因为这样解释起来更容易。假设互斥锁与条件变量正确使用以保持简单:

// 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() 之间存在很大差距,以 cmets 标记的一些其他代码的形式存在。这个差距意味着有时 notify_one() 在有机会调用 wait() 之前被调用。

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

我还考虑过使用wait() 谓词来标记一个允许其他线程通知的布尔值。我想这会起作用,因为wait() 是原子的,但我想知道是否有更好的方法。也许我处理的不正确。

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

【问题讨论】:

    标签: c++ multithreading thread-safety race-condition condition-variable


    【解决方案1】:

    简而言之:将条件变量视为一种通知其他线程发生变化的方法,而不仅仅是一个信号。

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

    现在,为了解决您的问题,线程 1 可以在准备好接收条件变量信号时使用带有就绪布尔值的条件变量向其他线程发出信号,但您最好先检查原始条件变量是否可以按照这里的描述使用。

    基于问题的伪代码(仍需要适当锁定条件变量):

    // 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-10
      • 1970-01-01
      相关资源
      最近更新 更多