【问题标题】:Why only std::atomic_flag is guaranteed to be lock-free?为什么只有 std::atomic_flag 保证是无锁的?
【发布时间】:2015-07-27 04:46:55
【问题描述】:

来自 C++ Concurrency in Action:

std::atomic 和 std::atomic_flag 的区别在于 std::atomic 可能不是无锁的;实现可能必须在内部获取互斥锁以确保操作的原子性

我想知道为什么。如果 atomic_flag 保证是无锁的,为什么不保证 atomic<bool> 也是如此? 这是因为成员函数compare_exchange_weak吗?我知道有些机器缺少一条比较和交换指令,是这个原因吗?

【问题讨论】:

  • 因为std::atomic<T> 有一个类型参数,所以 std::atomic_flag 没有。 T 更新是否是原子的取决于处理器架构。库编写者可以为 atomic_flag 选择任何合适的类型。
  • 好的。但是我的问题是关于std::atomic<bool>std::atomic_flag 之间的本质区别
  • 我觉得没什么区别

标签: c++ multithreading atomic lock-free stdatomic


【解决方案1】:

首先,你完全可以拥有像std::atomic<very_nontrivial_large_structure> 这样的东西,所以std::atomic 通常不能保证是无锁的(尽管大多数像boolint 这样的琐碎类型的特化可能可以,在大多数系统上)。但这有点无关。

在 N2427/29.3 的注释中给出了为什么 atomic_flag 而没有其他必须无锁的确切原因:

因此操作必须是无地址的。没有其他类型需要无锁操作,因此 atomic_flag 类型是符合该标准所需的最低硬件实现类型可以使用 atomic_flag 模拟其余类型,尽管属性不太理想。

换句话说,这是每个平台上必须保证的最低限度的事情,因此可以正确实施标准。

【讨论】:

  • 正确无用
  • @curiousguy:我不会这么说。在大多数平台上,所有小于 16 字节的类型(包括复合类型)都是无锁的。几乎所有的东西,除了一些微控制器或 35 岁的垃圾软件,所有的东西都最多 8 个字节。如果您需要了解,您可以查询您的实现,但更重要的是,您可以编写将工作无论如何,并且将在大多数架构上尽可能快地工作的代码。它实际上很酷。
  • 是的。 "你完全可以拥有类似 std::atomic" 你可以,但它不是很有用。
  • @curiousguy:再说一次,我不一定会这么说。在某些情况下,您有多个值(例如,显式服务员人数),并且您可能希望同时比较-交换其中一个或两个,具体取决于您的操作。因此,只要 size 低于某个两个指针大小的魔术常数,您就可以随心所欲地做您想做的事,并且它可以工作,这非常好。我希望有类似高速缓存行大小的原子(实际上为什么不......)。现在真的很酷。
  • 是的,但是“你有不止一个值”,一个 ptr 和一个使用计数,并不是一个非常大的结构。 very_nontrivial_large_structure 具有“数百字节大小”的内涵。或者可能只是我。
【解决方案2】:

该标准不保证原子对象是无锁的。在不为类型T 提供无锁原子操作的平台上,std::atomic<T> 对象可以使用互斥体实现,该互斥体不是无锁的。在这种情况下,任何在其实现中使用这些对象的容器也不会是无锁的。

该标准提供了检查std::atomic<T> 变量是否无锁的机会:您可以使用var.is_lock_free()atomic_is_lock_free(&var)。对于 int 等基本类型,还提供了宏(例如 ATOMIC_INT_LOCK_FREE),用于指定对该类型的无锁原子访问是否可用。

std::atomic_flag 是一个原子布尔类型。对于boolean 类型,几乎总是不需要使用互斥锁或其他同步方式。

【讨论】:

    猜你喜欢
    • 2017-09-18
    • 2021-06-05
    • 2020-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-30
    • 1970-01-01
    相关资源
    最近更新 更多