有原子的 |= 操作吗?

7

有没有原子性的|=或者原子或操作?如果没有,那么在需要线程安全的变量中设置位的推荐技术是什么?(我避免使用锁)

4个回答

7

在C++03中没有这样的东西,但是您可以使用供应商特定的功能。例如,在Windows上可以使用InterlockedOr。在C++0x中,您可以使用atomic_fetch_or

请注意,原子操作也需要锁定,尽管它在硬件级别上仍然很昂贵。


1
请注意,并非所有原子操作都需要锁定。有一些非阻塞原子算法可供使用。 - M Platvoet
1
@M:根据定义,原子操作需要锁定。执行操作的CPU核心在操作期间锁定内存总线,因此其他CPU无法访问内存。另外,并不存在所谓的“原子算法”,所以您可能不知道自己在说什么。抱歉。 - Yakov Galka
@M:当我在上面说“锁定”时,我指的是硬件级别的锁定,而不是互斥锁。 - Yakov Galka
@ybungalobill:虽然从技术上讲是正确的,但大多数架构在技术上确实会锁定主总线,无锁并不意味着“不做任何锁定操作”。在其适当的用法中,“无锁”表示在有限的时间内,至少有一个线程会取得进展。互斥锁不能保证这一点:如果一个线程获取了锁,一个精神病调度程序可能会选择只运行被阻塞的线程,导致没有进展。在“锁定内存总线”的情况下,处理器没有提供暂停锁定线程而不释放总线的方法,因此它符合“无锁”的定义。 - Cort Ammon
@CortAmmon:你说的都是对的,但我不明白它与本题有什么关系。我在谈论硬件级别的锁定(Windows API 的名称“interlocked-op”不是偶然的),而不是无锁算法(我猜这就是 M Platvoet 所说的)。 - Yakov Galka

4
您可以使用原子比较和交换(CAS)来实现几乎任何操作的原子版本,它在您可能需要的任何地方都可以使用。

嗯,这实际上适用于我需要实现的任何操作符。好主意。 - user34537
我想知道为什么“CAS”被称为“比较和交换”,而不是“比较和存储”,考虑到前者的名称听起来像“比较-交换”——这是CAS不能总是模拟而不会发生活锁的操作——而后者的名称描述了它的功能? - supercat
@supercat 因为,至少传统上它会返回最初读取的值?比较和设置更接近你想要的意思,使用相同的缩写以最大化混淆。 - Alan Stokes
@AlanStokes:许多关于CAS的描述都将其描述为具有通过-失败返回值(与compare-exchange不同,后者在失败的情况下返回观察到的值)。在CAS是通过-失败的硬件上,如果另一个处理器交替设置变量的期望值和其他值,则尝试合成compare-exchange可能会导致活锁。compare-exchange代码将读取变量,看到它与期望值匹配,尝试条件存储,观察到失败,重新读取变量,看到旧值,重试条件存储,以此类推。 - supercat
实际上,这样的活锁不太可能持续很长时间,但如果CAS失败并且调用代码只对通过-失败指示感兴趣,则CAS例程没有理由花费额外的精力尝试找到CAS失败时变量可能保存的内容。 - supercat

3

1

在当前的C++标准中,没有这样的功能 - 但是在C++11中将会有,该版本可能会在秋季发布。请参见:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1401.pdf

我不确定是否已经有编译器支持即将推出的C++标准的新线程工具的部分功能。否则,您需要使用解决方法(例如Boost)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接