c++ - 如果 std::atomic 仍然需要互斥锁才能正常工作,为什么还要使用它
问题描述
阅读文本std::condition_variable
我遇到了这句话:
即使共享变量是原子的,也必须在互斥锁下进行修改,才能正确地将修改发布到等待线程。
我的问题是这样的:
如果不是“与 POD 一起使用的无锁代码”,那么原子有什么用?
更新
看起来我的问题有些混乱:(
引用文本中的“共享变量”与“条件变量”不同。请参阅同一页面的此引用:
...直到另一个线程同时修改共享变量(条件),并通知条件变量
请不要回答“为什么我们需要使用带有条件变量的互斥锁”或“条件等待如何工作”,而是提供有关使用互斥锁如何“正确发布”对等待线程的原子修改的信息,即是否需要在互斥锁下完成类似++counter;
(而不是测试)的表达式?if(counter == 0)
解决方案
条件等待的语义需要使用互斥锁。
这是因为在测试条件的线程上存在潜在的竞争条件。当这个线程正在检查是否等待时,会发生以下情况:
- 获取排他锁
- 执行测试
任何一个:
a) 释放锁并等待下一个信号
b) 保持锁定并继续
因为步骤 1 获得了一个锁,所以整个事情都是原子的,前提是所有其他方都正确使用互斥锁。
但是当被修改的变量是原子的时候呢?
即使共享变量是原子的,也必须在互斥锁下进行修改,才能正确地将修改发布到等待线程。
嗯,这就是为什么。如果线程 B 出现并修改互斥锁之外的原子,则步骤 2 和 3 不再是原子的。本质上,线程 B 可以在步骤 2 发生后立即修改该值。那么线程 A 可能会在步骤 3 中做出错误的决定。
推荐阅读
- java - 使用 JasperFillManager.fillReport 方法得到“java.io.StreamCorruptedException: invalid stream header”
- assembly - ARM 汇编,在循环后使用 ldr 保持相同的 r2
- reactjs - 如何在类组件中使用 useSelector?
- algorithm - 资产价格是如何从证券交易所的订单簿中计算出来的?
- reactjs - 在反应钩子中输入输入数据到 api 的端点查询
- c - 如何使用循环停在特定数字
- xcode - 返回 int 以在 swiftUI 中用作变量
- c# - Unity中鼠标的反转
- python - 使用多个 start_url 抓取多个页面
- jupyter - 导入 ggplot 的问题:从 ggplot 导入 *