gpt4 book ai didi

multithreading - 为什么 std::condition_variable::wait 需要互斥锁?

转载 作者:行者123 更新时间:2023-12-04 06:48:43 25 4
gpt4 key购买 nike

TL; DR

为什么 std::condition_variable::wait 需要一个互斥体作为它的变量之一?

答案 1

您可以查看文档并引用:

 wait... Atomically releases lock

但这不是真正的原因。这只是进一步验证了我的问题:为什么它首先需要它?

答案 2

谓词最有可能查询共享资源的状态,它必须受到锁保护。

好的。公平的。
这里有两个问题
  • 谓词查询共享资源的状态总是正确的吗?我假设是的。否则对我来说实现它没有意义
  • 如果我不传递任何谓词(它是可选的)怎么办?

  • 使用谓词 - 锁定有意义
    int i = 0;
    void waits()
    {
    std::unique_lock<std::mutex> lk(cv_m);
    cv.wait(lk, []{return i == 1;});
    std::cout << i;
    }

    不使用谓词 - 为什么我们不能在等待后锁定?
    int i = 0;
    void waits()
    {
    cv.wait(lk);
    std::unique_lock<std::mutex> lk(cv_m);
    std::cout << i;
    }

    笔记

    我知道这种做法没有有害影响。我只是不知道如何向自己解释为什么它是这样设计的?

    问题

    如果谓词是可选的并且没有传递给 wait ,为什么我们需要锁?

    最佳答案

    当使用条件变量等待条件时,线程执行以下步骤序列:

  • 判断当前条件不为真。
  • 它开始等待其他线程使条件成立。这是 wait 调用。

  • 例如,条件可能是队列中有元素,一个线程可能看到队列为空并等待另一个线程将内容放入队列。

    如果另一个线程在这两个步骤之间进行调解,它可以使条件为真,并在第一个线程实际开始等待之前通知条件变量。在这种情况下,等待线程将不会收到通知,并且可能永远不会停止等待。

    要求持有锁的目的是防止其他线程像这样进行调解。此外,必须解锁锁以允许其他线程做我们正在等待的任何事情,但由于notify-before-wait问题,它不能在 wait调用之前发生,也不能在 wait调用之后发生因为我们在等待的时候什么也做不了。它必须是 wait 调用的一部分,所以 wait 必须知道锁。

    现在,您可能会看到 notify_*方法,并注意到这些方法不需要持有该锁,因此实际上没有什么可以阻止另一个线程在步骤1和2之间进行通知。但是,调用 notify_*的线程应该持有在执行它所做的任何操作以使条件为真时锁定,这通常是足够的保护。

    关于multithreading - 为什么 std::condition_variable::wait 需要互斥锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46088363/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com