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

2024-04-09

TL;DR

为什么std::condition_variable::等待 http://en.cppreference.com/w/cpp/thread/condition_variable/wait需要互斥锁作为其变量之一吗?


Answer 1

您可以查看文档并引用:

 wait... Atomically releases lock

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

Answer 2

谓词很可能查询共享资源的状态,并且必须受到锁保护。

好的。公平的。 这里有两个问题

  1. 总是这样吗谓词查询共享资源的状态?我想是的。否则对我来说实施它是没有意义的
  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;
}

Notes

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

Question

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


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

  1. 它确定条件当前不成立。
  2. 它开始等待其他线程使条件成立。这是wait call.

例如,条件可能是队列中有元素,并且线程可能会发现队列为空并等待另一个线程将元素放入队列中。

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

要求持有锁的目的是为了防止其他线程像这样介入。此外,必须解锁锁才能允许其他线程执行我们正在等待的任何操作,但这不能在wait由于notify-before-wait问题而调用,并且在wait之后不可能发生wait打电话是因为在等待期间我们无能为力。它必须是wait打电话,所以wait必须了解锁。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 std::condition_variable::wait 需要互斥锁? 的相关文章

  • 在 C++ 中使用 std::atomic 与 std::condition_variable 暂停和恢复 std::thread 的方法

    这是一个单独的问题 但与我问的上一个问题相关here https stackoverflow com questions 40544480 c correct way to pause resume an stdthread 4054476
  • java:使用2个线程打印奇偶数

    我正在尝试交替使用 2 个不同的线程打印奇数和偶数 我能够使用等待 通知和同步块来实现它 但现在我想评估我们是否可以在不使用等待 通知和同步的情况下实现它 以下是我的代码 但它不起作用 public class OddEvenUsingAt
  • 当现在允许使用虚拟基地移动分配运算符时,会有危险吗?

    这涉及到C 问题的解决http www open std org jtc1 sc22 wg21 docs cwg defects html 1402 http www open std org jtc1 sc22 wg21 docs cwg
  • 从单个应用程序中的多个线程调用 dll 函数是否安全?

    我正在 Delphi 2009 中编写一个服务器应用程序 它实现了多种类型的身份验证 每种身份验证方法都存储在单独的 dll 中 第一次使用身份验证方法时 会加载适当的 dll 仅当应用程序关闭时 DLL 才会被释放 在服务器线程 连接 之
  • Ruby IMAP IDLE 并发 - 如何解决?

    我正在尝试构建一个 目前是私有的 Web 应用程序 该应用程序将利用 IMAP IDLE 连接在人们到达时显示电子邮件 我很难弄清楚如何将其组合在一起 以及它如何与我的 Heroku RoR 服务器结合在一起 我编写了一个用于连接到 IMA
  • 如何迭代 std::index_sequence

    我的源代码中有这段代码 template
  • 在 C++11 中使用 max 作为谓词会中断

    在 C 03 中 以下代码工作正常 int main std vector
  • 双重检查锁定模式

    In 有伪代码来正确实现作者建议的模式 见下文 Singleton Singleton instance Singleton tmp pInstance insert memory barrier 1 if tmp 0 Lock lock
  • 使用步骤 c++ 构建向量

    是否可以在不使用 C 中的循环的情况下以固定步骤创建从一个值到另一个值的向量 例如 我想用步长 0 5 构建一个从 1 到 10 的向量 在 MATLAB 中我可以按如下方式执行此操作 vector 1 0 5 10 c 中有类似的东西吗
  • c++1y 模式下的 Clang >= 3.3 无法解析 标头

    我有一个项目可以在 g 4 8 1 和 c 11 模式下 clang gt 3 3 下正确编译和运行 然而 当我切换到实验时 std c 1y模式下 clang 3 3 但不是 g 在
  • 跟踪 pthread 调度

    我想做的是创建某种图表 详细说明 Linux 中 两个 线程的执行情况 我不需要查看线程的作用 只需查看它们何时被安排以及持续多长时间 基本上是一条时间线 在过去的几个小时里 我一直在互联网上搜索跟踪 pthread 调度的方法 不幸的是
  • 是否有可能在 C++ 中获取 std::array 的子数组?

    我想做类似的事情 std array
  • 如何使用 Handler.Post() 通知工作线程 UI 被修改?

    我有一个工作线程 偶尔我会使用以下命令向 UI 线程发送更新Handler Post 在某些情况下 我需要工作线程等待Handler Post 在 UI 线程上执行and视图被修改并且afterUI线程被修改 通知worker线程继续 这是
  • C# 系统 CPU 使用情况并与 Windows 任务管理器同步

    这是一个由两部分组成的问题 我想将我的代码发布到堆栈上以帮助其他人完成相同的任务 问题一 我有一个代码子集 我相信它可以根据测量间隔正确测量 CPU 使用情况 根据检索的时间跨系统中的尽可能多的核心 我在线程调用中使用 1 秒 我必须从网上
  • 导出类时编译器错误

    我正在使用 Visual Studio 2013 但遇到了一个奇怪的问题 当我导出一个类时 它会抛出 尝试引用已删除的函数 错误 但是 当该类未导出时 它的行为会正确 让我举个例子 class Foo note the export cla
  • 从 C 线程调用 Python 代码

    我对从 C 或 C 线程调用 Python 代码时如何确保线程安全感到非常困惑 The Python 文档 http docs python org c api init html non python created threads似乎是
  • C++ 在循环中创建线程时出错

    我在 Visual Studio 2015 中运行以下命令时遇到问题 include
  • C++ 模板 typedef

    我有课 template
  • 判断线程是否已经启动

    如何判断Python线程是否已经启动 有一个方法is alive 但这是真的before and while一个线程正在运行 你可以看看ident领域的Thread实例 这Python 2 7 线程文档 http docs python o
  • 监控 Java 应用程序上的锁争用

    我正在尝试创建一个小基准 在 Groovy 中 以显示几个同步方法上的高线程争用 当监控自愿上下文切换时 应该会出现高争用 在 Linux 中 这可以通过 pidstat 来实现 程序如下 class Res private int n s

随机推荐