使用“memory_order::relaxed”或“memory_order::acq_rel”生成唯一ID?

问题描述 投票:0回答:1

我在几个地方读到过宽松的排序可以生成唯一的 ID。我对此有疑问,因为如果两个线程同时调用:

uniqueId.fetch_add(1, std::memory_order::relaxed);

然后线程 A 增加的值可能对线程 B 不可见。这意味着,两个线程可以获得相同的唯一 ID。

出于这个原因,我宁愿使用

std::memory_order::acq_rel

你怎么看?

在实践中无法测试。

c++ atomic stdatomic memory-model
1个回答
7
投票

std::memory_order_*
是关于如何存储和加载到内存位置other 而不是原子对象本身同步。

单个原子对象的值在所有线程中总是一致的。它只有一个所有线程都同意的修改顺序,并且与每个线程中的加载/存储顺序一致,无论

std::memory_order_*
.

(然而,这仅适用于单独查看的每个原子对象。这同样不适用于多个原子对象。)

std::memory_order::relaxed
在您的情况下是否足够取决于生成的 ID 值是否将通过线程之间的其他共享对象(无论是否为原子)使用,但是表达式

uniqueId.fetch_add(1, std::memory_order::relaxed)

,即使在多个线程中使用,每个 ID 也只会生成一次(假设

uniqueId
指的是同一个
std::atomic
对象,没有其他存储应用于它并且没有溢出/环绕发生)。重要的是
fetch_add
本身是一个原子读-修改-写。加载后跟存储不是原子操作,也不能保证没有来自另一个线程的存储介入加载和存储之间。

© www.soinside.com 2019 - 2024. All rights reserved.