问题标签 [compare-and-swap]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
3 回答
11473 浏览

java - Java 比较和交换语义和性能

Java中比较和交换的语义是什么?即,比较和交换方法是否AtomicInteger只保证不同线程之间对原子整数实例的特定内存位置的有序访问,或者它是否保证对内存中所有位置的有序访问,即它的行为就好像它是易失性的(记忆栅栏)。

文档

  • weakCompareAndSet原子地读取和有条件地写入变量,但不会创建任何发生前的顺序,因此不保证对除weakCompareAndSet.
  • compareAndSet以及所有其他读取和更新操作,例如getAndIncrement具有读取和写入 volatile 变量的记忆效应。

从 API 文档中可以明显看出,compareAndSet它就像一个 volatile 变量。但是,weakCompareAndSet应该只是更改其特定的内存位置。因此,如果该内存位置专用于单个处理器的缓存,weakCompareAndSet则应该比常规的compareAndSet.

我之所以问这个问题是因为我通过运行threadnum不同的线程(threadnum从 1 到 8 不等)并拥有totalwork=1e9(代码是用静态编译的 JVM 语言 Scala 编写的,但它的含义和字节码翻译都是同构的)对以下方法进行了基准测试在这种情况下是 Java - 这个简短的片段应该很清楚):

在具有 4 个双 2.8 GHz 内核和 2.67 GHz 4 核 i7 处理器的 AMD 上。JVM 是 Sun Server Hotspot JVM 1.6。结果显示没有性能差异。

规格:AMD 8220 4x 双核 @ 2.8 GHz

测试名称:loop_atomic_tlocal_cas

  • 线程数:1

运行时间:(显示最后 3 个)7504.562 7502.817 7504.626(平均 = 7415.637 最小 = 7147.628 最大 = 7504.886)

  • 线程数:2

运行时间:(显示最后 3 个)3751.553 3752.589 3751.519(平均 = 3713.5513 最小值 = 3574.708 最大值 = 3752.949)

  • 线程数:4

运行时间:(显示最后 3 个)1890.055 1889.813 1890.047(平均 = 2065.7207 最小值 = 1804.652 最大值 = 3755.852)

  • 线数:8

运行时间:(显示最后 3 个)960.12 989.453 970.842(平均 = 1058.8776 最小值 = 940.492 最大值 = 1893.127)


测试名称:loop_atomic_weakcas

  • 线程数:1

运行时间:(显示最后 3 个)7325.425 7057.03 7325.407(平均 = 7231.8682 最小值 = 7057.03 最大值 = 7325.45)

  • 线程数:2

运行时间:(显示最后 3 个)3663.21 3665.838 3533.406(平均 = 3607.2149 最小值 = 3529.177 最大值 = 3665.838)

  • 线程数:4

运行时间:(显示最后 3 个)3664.163 1831.979 1835.07(平均 = 2014.2086 最小值 = 1797.997 最大值 = 3664.163)

  • 线数:8

运行时间:(显示最后 3 个)940.504 928.467 921.376(平均 = 943.665 最小值 = 919.985 最大值 = 997.681)


测试名称:loop_atomic_tlocal_weakcas

  • 线程数:1

运行时间:(显示最后 3 个)7502.876 7502.857 7502.933(平均 = 7414.8132 最小值 = 7145.869 最大值 = 7502.933)

  • 线程数:2

运行时间:(显示最后 3 个)3752.623 3751.53 3752.434(平均 = 3710.1782 最小值 = 3574.398 最大值 = 3752.623)

  • 线程数:4

运行时间:(显示最后 3 个)1876.723 1881.069 1876.538(平均 = 4110.4221 最小值 = 1804.62 最大值 = 12467.351)

  • 线数:8

运行时间:(显示最后 3 个)959.329 1010.53 969.767(平均 = 1072.8444 最小值 = 959.329 最大值 = 1880.049)

规格:Intel i7 四核 @ 2.67 GHz

测试名称:loop_atomic_tlocal_cas

  • 线程数:1

运行时间:(显示最后 3 个)8138.3175 8130.0044 8130.1535(平均值 = 8119.2888 最小值 = 8049.6497 最大值 = 8150.1950)

  • 线程数:2

运行时间:(显示最后 3 个)4067.7399 4067.5403 4068.3747(平均 = 4059.6344 最小值 = 4026.2739 最大值 = 4068.5455)

  • 线程数:4

运行时间:(显示最后 3 个)2033.4389 2033.2695 2033.2918(平均 = 2030.5825 最小 = 2017.6880 最大 = 2035.0352)


测试名称:loop_atomic_weakcas

  • 线程数:1

运行时间:(显示最后 3 个)8130.5620 8129.9963 8132.3382(平均 = 8114.0052 最小值 = 8042.0742 最大值 = 8132.8542)

  • 线程数:2

运行时间:(显示最后 3 个)4066.9559 4067.0414 4067.2080(平均值 = 4086.0608 最小值 = 4023.6822 最大值 = 4335.1791)

  • 线程数:4

运行时间:(显示最后 3 个)2034.6084 2169.8127 2034.5625(平均 = 2047.7025 最小值 = 2032.8131 最大值 = 2169.8127)


测试名称:loop_atomic_tlocal_weakcas

  • 线程数:1

运行时间:(显示最后 3 个)8132.5267 8132.0299 8132.2415(平均值 = 8114.9328 最小值 = 8043.3674 最大值 = 8134.0418)

  • 线程数:2

运行时间:(显示最后 3 个)4066.5924 4066.5797 4066.6519(平均 = 4059.1911 最小值 = 4025.0703 最大值 = 4066.8547)

  • 线程数:4

运行时间:(显示最后 3 个)2033.2614 2035.5754 2036.9110(平均 = 2033.2958 最小值 = 2023.5082 最大值 = 2038.8750)


虽然上面示例中的线程局部变量可能最终位于相同的缓存行中,但在我看来,常规 CAS 与其弱版本之间没有明显的性能差异。

这可能意味着,事实上,弱比较和交换就像完全成熟的内存栅栏一样,即就像它是一个易失性变量一样。

问:这个观察正确吗?此外,是否存在已知的架构或 Java 发行版,其弱比较和设置实际上更快?如果不是,那么首先使用弱 CAS 有什么好处?

0 投票
2 回答
3120 浏览

c++ - 比较和交换 C++0x

来自关于 C++ 原子类型和操作的C++0x 提案:

29.1 顺序和一致性 [atomics.order]

添加带有以下段落的新子条款。

枚举memory_order指定详细的常规(非原子)内存同步顺序,如[N2334 或其采用的后续程序添加的新部分] 中定义的,并且可以提供操作顺序。其枚举值及其含义如下。

  • memory_order_relaxed

该操作不对内存进行排序。

  • memory_order_release

对受影响的内存位置执行释放操作,从而通过应用它的原子变量使常规内存写入对其他线程可见。

  • memory_order_acquire

对受影响的内存位置执行获取操作,从而使通过应用它的原子变量释放的其他线程中的常规内存写入对当前线程可见。

  • memory_order_acq_rel

该操作具有获取和释放语义。

  • memory_order_seq_cst

该操作具有获取和释放语义,此外,还具有顺序一致的操作顺序。

提案中较低的:

可以指定 CAS 的内存顺序。


我的理解是“<code>memory_order_acq_rel”只会同步操作所需的那些内存位置,而其他内存位置可能保持不同步(它不会充当内存围栏)。

现在,我的问题是 - 如果我选择“<code>memory_order_acq_rel”并应用于compare_swap整数类型,例如整数,这通常如何转换为现代消费处理器(如多核 Intel i7)上的机器代码?其他常用的架构(x64、SPARC、ppc、arm)呢?

特别是(假设一个具体的编译器,比如 gcc):

  1. 如何使用上述操作比较和交换整数位置?
  2. 这样的代码会产生什么指令序列?
  3. i7的操作是无锁的吗?
  4. 这样的操作会运行完整的缓存一致性协议,同步不同处理器内核的缓存,就好像它是 i7 上的内存栅栏一样?还是只会同步此操作所需的内存位置?
  5. acq_rel与上一个问题相关 -在 i7 上使用语义是否有任何性能优势?其他架构呢?

感谢所有的答案。

0 投票
5 回答
4063 浏览

c - 在 C 中比较和交换机器代码

您将如何使用嵌入式机器代码(假设,假设 x86 架构)在 C 中编写一个对整数值进行原子比较和交换的函数?如果它只为 i7 处理器编写,它可以更具体吗?

翻译是否充当记忆栅栏,或者它只是确保在比较和交换中包含的那个记忆位置上的排序关系?与内存围栏相比,它的成本是多少?

谢谢你。

0 投票
1 回答
735 浏览

c++ - 尝试创建 CAS 模板

目前我正忙于摆弄 CAS 操作和无锁/无等待算法,为了我自己的理智,我决定实现一个模板来为我处理所有的转换:

VC6:

海湾合作委员会 4.4.1:

但是,使用一些简单的测试代码,我无法让它在volatile目的地上工作,这是防止重新排序所必需的。

测试代码:

在 VC6 下我得到这个错误:

和 GCC 吐出这个:

volatile是否有可能为 CAS ops 获得一个模板,当目标是或我被宏卡住时不会中断?

0 投票
1 回答
1410 浏览

c++ - 需要帮助理解“ABA”问题

我读了一篇文章,描述了 ABA 问题,但有些东西我无法理解。我有源代码,它无法工作,它与文章中的示例类似,但我不明白这个问题。这是文章

http://fara.cs.uni-potsdam.de/~jsg/nucleus/index.php?itemid=6

它说:虽然 head_ 的实际值是相同的(a)next_ 指针不是

但怎么可能呢?如果两个结构对象

“head_”和“current”指向内存中的同一个区域,head_->next和current->next怎么能指向不同呢?

它还说:最后一个操作, foo 的比较和交换在它不应该成功的时候成功。

那么它应该怎么做呢?加载相同的地址并重试?有什么不同?

目前在我的代码中我有类似的情况,我在对象上执行 CompareAndSwap,这可能会被另一个线程更改为具有相似地址的对象

但是如果更改的对象初始化良好并且它的下一个指针包含指向初始化对象的指针,那么问题是什么?

提前致谢。

0 投票
5 回答
7381 浏览

c++ - CMPXCHG16B 正确吗?

尽管我不确定为什么,但这似乎并不完全正确。建议会很好,因为 CMPXCHG16B 的文档非常少(我没有任何英特尔手册......)

当运行一个示例时,我得到 0 而它应该是 1。有什么想法吗?

0 投票
1 回答
1142 浏览

memcached - EhCache 中的比较和交换 (CAS) 实现

我试图在 EhCache 中找到 MemCache 的 CASMutator.cas 的等效项。本质上,我正在将 EhCache 换成 MemCache,并且需要实现一个接口,该接口调用通过 CAS 设置值。有没有人对此有任何见解?此外,鉴于我并不声称自己是这方面的专家,如果有人对 CAS 的实际工作方式/它正在做什么有任何高层次的概述,那也将不胜感激。

0 投票
1 回答
1671 浏览

multithreading - 共识价值

在阅读并发编程时,我在 Compare-And-Swap 和 Compare-And-Set 操作中遇到了Consensus Number一词。我很难理解这个术语的含义,谁能解释一下?

谢谢你!!

0 投票
5 回答
2350 浏览

c# - 为什么要使用双重检查锁定?

我一直在运行使用双重检查锁定的代码,但我仍然对为什么要使用它感到困惑。

我一开始并不知道双重检查锁定是坏的,当我学会它时,它对我来说放大了这个问题:为什么人们首先要使用它?比较和交换不是更好吗?

(我的问题同时适用于 C# 和 Java,尽管上面的代码适用于 C#。)

与原子操作相比,双重检查锁定是否具有某种内在优势?

0 投票
2 回答
5430 浏览

c++ - 比较和交换原子操作与加载链接/存储条件操作

在 x86 处理器下,我不确定比较和交换原子操作和加载链接/存储条件操作之间的区别。后者比前者更安全吗?是不是第一个比第二个好?