C ++条件变量notify_one:释放锁定之前还是之后?

时间:2019-03-14 03:21:43

标签: c++ multithreading

下面是一些有关CPPConference.com中C ++条件变量的代码示例:

std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;

void worker_thread()
{
    // Wait until main() sends data
    std::unique_lock<std::mutex> lk(m);
    cv.wait(lk, []{return ready;});

    // after the wait, we own the lock.
    std::cout << "Worker thread is processing data\n";
    data += " after processing";

    // Send data back to main()
    processed = true;
    std::cout << "Worker thread signals data processing completed\n";

    // Manual unlocking is done before notifying, to avoid waking up
    // the waiting thread only to block again (see notify_one for details)
    lk.unlock();
    cv.notify_one();
}

我不太了解在通知另一个线程之前释放锁的末尾部分。

  1. 如果代码在lk.unlock()之前放置了cv.notify_one()是否可行?
  2. 为什么最好将cv.notify_one()放在lk.unlock()之后?根据{{​​3}},“通知线程不需要将锁与等待线程持有的互斥锁保持在同一互斥锁上;实际上这样做是一种悲观,因为被通知线程将立即阻塞再次,等待通知线程释放锁。”但是,在我看来,将notify_one放在解锁之前会导致notify-> unlock->另一个线程获得锁,而将notify_one放在解锁之后会导致unlock-> notify->另一个线程获得锁。 。这里有什么区别?

1 个答案:

答案 0 :(得分:0)

  1. 该链接是正确的,如果两个通知线程都具有锁,则被通知的线程必须阻塞,直到通知线程释放锁为止。在多核处理器中,这是不必要的延迟。

您的比较存在缺陷,因为它缺少详细信息。有两个线程同时运行,因此您的比较省略了。

在解锁之前放入notify_one:

notifying thread: notify -> eventually release lock
notified thread: awaken -> attempt to acquire lock and fail -> block until lock available -> acquire lock after notifying thread releases it

解锁后放入notify_one:

notifying thread: notify 
notified thread: awaken -> attempt to acquire lock and succeed
相关问题