标签: compare-and-swap

为什么要使用双重锁定?

我继续运行使用双重检查锁定的代码,我仍然对它为什么会被使用感到困惑.

我最初不知道双重检查锁定是否被打破,当我学会它时,它为我放大了这个问题:为什么人们首先使用它?是不是比较和交换更好?

if (field == null)
    Interlocked.CompareExchange(ref field, newValue, null);
return field;
Run Code Online (Sandbox Code Playgroud)

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

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

c# java synchronization compare-and-swap double-checked-locking

5
推荐指数
2
解决办法
2087
查看次数

std :: atomic <int*> :: load应该进行比较和交换循环吗?

简介:我曾预料到,只要加载的值很少改变std::atomic<int*>::load,std::memory_order_relaxed就会接近直接加载指针的性能.我看到原子负载的性能远远低于Visual Studio C++ 2012上的正常负载,因此我决定进行调查.事实证明原子负载是作为比较和交换循环实现的,我怀疑它不是最快的实现.

问题:是否有某些原因std::atomic<int*>::load需要进行比较和交换循环?

背景:我相信MSVC++ 2012正在基于此测试程序对指针的原子加载进行比较和交换循环:

#include <atomic>
#include <iostream>

template<class T>
__declspec(noinline) T loadRelaxed(const std::atomic<T>& t) {
  return t.load(std::memory_order_relaxed);
}

int main() {
  int i = 42;
  char c = 42;
  std::atomic<int*> ptr(&i);
  std::atomic<int> integer;
  std::atomic<char> character;
  std::cout
    << *loadRelaxed(ptr) << ' '
    << loadRelaxed(integer) << ' '
    << loadRelaxed(character) << std::endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我正在使用一个__declspec(noinline)函数来隔离与原子负载相关的汇编指令.我做了一个新的MSVC++ 2012项目,添加了一个x64平台,选择了发布配置,在调试器中运行程序并查看了反汇编.事实证明,两者std::atomic<char>std::atomic<int>参数最终会给出相同的调用loadRelaxed<int>- 这必须是优化器所做的事情.这是被调用的两个loadRelaxed实例的反汇编:

loadRelaxed<int …

c++ atomic visual-c++ compare-and-swap visual-studio-2012

5
推荐指数
1
解决办法
1437
查看次数

为bool实现CompareAndSwap

在.NET框架中,原子操作CompareAndExchange仅对定义int,long,double和引用类型.但我需要CompareAndExchange bool类型.我怎样才能实现CompareAndSwapbool

c# boolean compare-and-swap

5
推荐指数
1
解决办法
189
查看次数

atomic_cmpxchg()是否暗示内存壁垒?

以下两个引用似乎矛盾:

https://www.kernel.org/doc/Documentation/atomic_ops.txt

int atomic_cmpxchg(atomic_t * v,int old,int new);

这会对具有给定的旧值和新值的原子值v执行原子比较交换操作。像所有atomic_xxx操作一样,只要通过atomic_xxx操作执行* v的所有其他访问,atomic_cmpxchg将仅满足其原子性语义。

atomic_cmpxchg需要在操作周围使用显式的内存屏障。

https://www.kernel.org/doc/Documentation/memory-barriers.txt

任何修改内存中某些状态并返回状态信息(旧的或新的)的原子操作都意味着在实际操作的每一端都存在一个SMP条件的通用内存屏障(smp_mb())(除了显式锁定操作,已描述)后来)。这些包括:

      <...>   
      atomic_xchg();  
      atomic_cmpxchg();
      <...> 
Run Code Online (Sandbox Code Playgroud)

这些用于实现LOCK类和UNLOCK类操作以及针对对象破坏调整参考计数器的事情,因此隐式内存屏障效应是必需的。

因此,应该atomic_xchg()手动消除内存障碍吗?

multithreading synchronization atomic linux-kernel compare-and-swap

5
推荐指数
1
解决办法
1454
查看次数

为什么在没有LOCK前缀的情况下,MESI协议不能保证x86上CMPXCHG的原子性?

我知道,MESI协议成功地保证了不同内核的内存(缓存)视图相同。我的问题来自这样一个事实,即在写入过程中,MESI保证高速缓存由CPU独占,然后原子CMPXCHG只是原子地比较和交换值。那么,当我们已经有了MESI协议的保证时,为什么还要使用LOCK指令来锁定高速缓存行呢?

x86 atomic cpu-architecture compare-and-swap mesi

5
推荐指数
1
解决办法
159
查看次数

为什么 CAS(原子)操作比同步或易失性操作更快

据我了解,synchronized关键字将本地线程缓存与主内存同步。volatile 关键字基本上总是在每次访问时从主内存中读取变量。当然,访问主内存比本地线程缓存要昂贵得多,因此这些操作的成本很高。然而,CAS 操作使用低级硬件操作,但仍然必须访问主存储器。那么 CAS 操作如何更快呢?

atomic compare-and-swap

4
推荐指数
1
解决办法
3314
查看次数

memory_order_relaxed 和 Atomic RMW 操作

C++ 标准说,原子上的 RMW(读-修改-写)操作将对原子变量的最新值进行操作。因此memory_order_relaxed,当从多个线程并发执行时,使用这些操作不会影响 RMW 操作。

我假设只有当 RMW 操作存在一些内存屏障或栅栏时,即使指定的内存顺序是“放松的”,这种行为也是可能的。如果我的理解有误,请纠正我,并解释如果不使用此类内存屏障,这些操作如何处理最新值。如果我的理解是正确的,那么我是否可以进一步假设使用 Acquire-Release 或 Seq-CST 内存顺序不应该对 RMW 操作产生额外的性能影响,比如 ARM 或 Alpha 等弱排序架构。提前致谢。

c++ multithreading memory-model compare-and-swap stdatomic

4
推荐指数
1
解决办法
595
查看次数

基于compare_exchange的循环是否受益于暂停?

在基于 CAS 的循环中,例如下面的循环,使用暂停对 x86 有益吗?

void atomicLeftShift(atomic<int>& var, int shiftBy)
{
    While(true) {
        int oldVal = var;
        int newVal = oldVal << shiftBy;
         if(var.compare_exchange_weak(oldVal, newVal));
             break;
        else
            _mm_pause();
    }
}
Run Code Online (Sandbox Code Playgroud)

c++ x86 atomic compare-and-swap c++11

4
推荐指数
1
解决办法
610
查看次数

&lt;atomic&gt; 的 CMPXCHG16B 和 MSVC 实现不是默认的?

似乎要使用 CMPXCHG16B,必须定义 _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B = 1 以便使用这些指令。

为什么这是默认设置?除非我阅读整个 atomic.h 标头,否则我永远不会发现这一点。

STL 中还有哪些其他全局定义?是否有一份清单可供审查,以便人们能够可靠地了解这些实施细节?

c++ x86-64 visual-c++ compare-and-swap stdatomic

4
推荐指数
1
解决办法
146
查看次数

没有真正理解 std::atomic::compare_exchange_weak 和compare_exchange_strong 的逻辑

我读过https://en.cppreference.com/w/cpp/atomic/atomic/compare_exchange

以原子方式将 *this 的对象表示形式 (C++20 之前) 值表示形式 (C++20 起) 与预期的表示形式进行比较,如果它们按位相等,则将前者替换为所需的(执行读取-修改-写入操作) )。否则,将 *this 中存储的实际值加载到预期中(执行加载操作)。

据我了解,代码如下

bool expected=true;
extern atomic<bool> b = false; 
void foo ()
{
//
    while(!b.compare_exchange_weak(expected, false));
//
}
Run Code Online (Sandbox Code Playgroud)

循环运行一次后(忽略虚假失败)它将失败,并将写入预期false,因此在第二次迭代时,compare_exchange_weak将返回成功,尽管b尚未更改为true。但这一切有什么意义呢?我虽然可以用它作为同步锁,等待其他线程更改b,但现在我想不出它的用法。

cppreference 中的示例还表明,两次调用compare_exchange_strong 后将会成功。

#include <atomic>
#include <iostream>
 
std::atomic<int>  ai;
 
int  tst_val= 4;
int  new_val= 5;
bool exchanged= false;
 
void valsout()
{
    std::cout << "ai= " << ai
          << "  tst_val= " << tst_val
          << "  new_val= " << new_val
          << "  exchanged= …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading atomic compare-and-swap stdatomic

4
推荐指数
1
解决办法
1066
查看次数