我正在尝试理解“比较和交换”操作,简称为CAS。我发现它有一个名为“比较和设置”的变体。它们的工作方式相同,但返回值不同。“比较和交换”返回值,而“比较和设置”返回布尔值。我的问题是它们是否在底层使用相同的Compare And Exchange(CMPXCHG for x86)指令。它们都是由Java中的原子类实现的吗?
CMPXCHG
iklwldmw1#
是的,它是一个 Package 器,公开了x86 lock cmpxchg或其他ISA上等效的compare-and-swap指令/序列的功能。但是Java的旧compareAndSet API只返回布尔值成功,而不是失败时的旧值,所以有些事情它不能完全做到。最近的一个问题 * Java 8 impl on Compare And Exchange (Not Compare and Set!) * 是关于模拟Java 17 compareAndExchange(返回旧值)--这不可能精确地完成。你可以在交换的时候加载一个值,但是即使你的CAS失败了,它也可能和你的CAS的“期望”参数一样结束。但是如果你把布尔值和你读的值分开,这对于大多数算法来说都是可以的。这种情况类似于GNU C's old __sync_bool_compare_and_swap与__sync_val_...,前者需要旧值,后者更强大:您 * 可以 * 通过自己比较返回值从val版本中获得成功/失败。因此,从Java8到Java 17,Java只提供了功能较弱的版本,这有点令人失望,尽管它是许多算法更可能使用的版本。(GNU C后来添加了__atomic内置函数,它与compare_exchange_weak的C++11 API相匹配,带有一个bool返回值和第一个引用参数,在CAS失败时更新。因此,您可以获得其中一个或两个,这取决于您实际使用的输出。)还相关:
lock cmpxchg
compareAndSet
compareAndExchange
__sync_bool_compare_and_swap
__sync_val_...
val
__atomic
compare_exchange_weak
1条答案
按热度按时间iklwldmw1#
是的,它是一个 Package 器,公开了x86
lock cmpxchg
或其他ISA上等效的compare-and-swap指令/序列的功能。但是Java的旧compareAndSet
API只返回布尔值成功,而不是失败时的旧值,所以有些事情它不能完全做到。最近的一个问题 * Java 8 impl on Compare And Exchange (Not Compare and Set!) * 是关于模拟Java 17
compareAndExchange
(返回旧值)--这不可能精确地完成。你可以在交换的时候加载一个值,但是即使你的CAS失败了,它也可能和你的CAS的“期望”参数一样结束。但是如果你把布尔值和你读的值分开,这对于大多数算法来说都是可以的。这种情况类似于GNU C's old
__sync_bool_compare_and_swap
与__sync_val_...
,前者需要旧值,后者更强大:您 * 可以 * 通过自己比较返回值从val
版本中获得成功/失败。因此,从Java8到Java 17,Java只提供了功能较弱的版本,这有点令人失望,尽管它是许多算法更可能使用的版本。(GNU C后来添加了
__atomic
内置函数,它与compare_exchange_weak
的C++11 API相匹配,带有一个bool返回值和第一个引用参数,在CAS失败时更新。因此,您可以获得其中一个或两个,这取决于您实际使用的输出。)还相关: