首页 > 解决方案 > 如果 std::atomic 仍然需要互斥锁才能正常工作,为什么还要使用它

问题描述

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

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

我的问题是这样的:

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

更新

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

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

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

请不要回答“为什么我们需要使用带有条件变量的互斥锁”或“条件等待如何工作”,而是提供有关使用互斥锁如何“正确发布”对等待线程的原子修改的信息,即是否需要在互斥锁下完成类似++counter;而不是测试)的表达式?if(counter == 0)

标签: c++mutexatomicstdatomicstdmutex

解决方案


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

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

  1. 获取排他锁
  2. 执行测试
  3. 任何一个:

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

    b) 保持锁定并继续

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

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

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

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


推荐阅读