【问题标题】:why use std::atomic if it still requires a mutex to work properly如果 std::atomic 仍然需要互斥锁才能正常工作,为什么还要使用它
【发布时间】:2023-03-04 14:20:01
【问题描述】:

阅读std::condition_variable的文字我遇到了这句话:

即使共享变量是原子的,也必须在互斥体下进行修改,才能正确地将修改发布到等待线程。

我的问题是这样的:

如果不是“用于 POD 的无锁代码”,那么原子有什么用?

更新

看来我的问题有些混乱:(

引用文本中的“共享变量”与“条件变量”不同。请参阅同一页面的此引用:

...直到另一个线程同时修改共享变量(条件),并通知条件变量

请不要回答“why we need to use a mutex with condition variables”或“how the conditional wait works”,而是提供有关使用互斥锁如何“正确发布”对等待线程的原子修改的信息,即是否像@987654325 这样的表达式@(不是if(counter == 0)这样的测试)需要在互斥锁下完成吗?

【问题讨论】:

  • 需要互斥锁的不是原子——它是条件变量。您的实际问题似乎与您引用的信息无关。
  • 该文本专门针对condition_variable,而不是一般的原子。原子变量处理的不仅仅是条件。
  • 我已经更新了我的问题,希望能更清楚
  • 嗯,我看到你用需求更新了你的问题。原子的修改不会“发布”任何东西。这就是 signal(又名通知)的工作。你得到关于条件等待的答案的全部原因是因为这正是问题所在——信号是原子的,但前提是条件变量内的依赖数据的处理是原子的。

标签: c++ mutex atomic stdatomic stdmutex


【解决方案1】:

条件等待的语义需要使用互斥体。

这是因为在测试条件的线程上存在潜在的竞争条件。当这个线程在检查是否等待时,会发生以下情况:

  1. 获取排他锁
  2. 执行测试
  3. 要么:

    a) 释放锁并等待下一个信号

    b) 保持锁定并继续

因为第 1 步获得了一个锁,所以整个事情都是原子的,前提是所有其他方都正确使用了互斥锁。

但是当被修改的变量是原子的时候呢?

即使共享变量是原子的,也必须在互斥体下进行修改,才能正确地将修改发布到等待线程。

嗯,这就是原因。如果线程 B 出现并修改互斥锁之外的原子,则步骤 2 和 3 不再是原子的。本质上,线程 B 可以在步骤 2 发生后立即修改该值。那么线程 A 可能会在步骤 3 中做出错误的决定。

【讨论】:

    【解决方案2】:

    如果 [条件变量] 仍然需要互斥锁才能正常工作,为什么要使用 std::atomic

    没有理由使用原子条件变量。

    原子有什么用

    即使原子对条件变量没有用处,它们仍然可以用于其他用例。原子的一个典型用例是实现无锁队列。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-15
      • 2018-07-25
      • 1970-01-01
      • 2020-05-04
      • 1970-01-01
      • 1970-01-01
      • 2021-08-08
      • 1970-01-01
      相关资源
      最近更新 更多