自动读取值的函数

Functions to atomically read a value?

本文关键字:函数 读取      更新时间:2023-10-16

我目前正在使用原子读和写,并且在我的理解中遇到了瓶颈。我理解写入变量(例如通过增量)必须是原子的,但我不确定是否读取变量。

考虑Windows上的_InterlockedExchangeAdd,或Linux上的__sync_add_and_fetch。我找不到自动检索正在更新的值的函数。现在我已经做了我的研究之前张贴在这里和c++读写int原子吗?告诉我读操作不是原子的

1)如果我使用上面的函数,我如何自动地读取值,如果从函数返回它?

2)如果我不想使用这些函数,只是想在每次写我的"原子"变量之前锁定互斥锁,在检索变量的当前值的函数中,我需要先锁定互斥锁,复制当前值,解锁互斥锁然后返回副本吗?

编辑

我使用的编译器不能访问原子头文件,因此必须使用这些api

你找不到答案,因为没有一种方法可以做到(a)快速和(b)可移植。这取决于:c++或C,编译器,编译器版本,编译器设置,库,架构…这样的例子不胜枚举。

起始点:

  • 如果你有访问标准原子或然后使用atomic_load() -它是便携式和快速。
  • 如果你没有标准的原子,那么使用CAS。例如,在Windows上,它将是_InterlockedCompareExchange(,0,0)。见https://msdn.microsoft.com/en-us/library/ms686355 (VS.85) . aspx。在Linux上是__sync_val_compare_and_swap(, 0, 0)。参见https://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Atomic-Builtins.html。
  • 如果你想使用直接赋值,那么你应该向知道代码将在哪里运行的专家咨询。

我碰巧有一段汇编程序代码,它可以解释为什么CAS是一个合理的选择。这是C, i86,微软编译器VS2015, Win64目标:

volatile long debug_x64_i = std::atomic_load((const std::_Atomic_long *)&my_uint32_t_var);
00000001401A6955  mov         eax,dword ptr [rbp+30h] 
00000001401A6958  xor         edi,edi 
00000001401A695A  mov         dword ptr [rbp-0Ch],eax 
    debug_x64_i = _InterlockedCompareExchange((long*)&my_uint32_t_var, 0, 0);
00000001401A695D  xor         eax,eax 
00000001401A695F  lock cmpxchg dword ptr [rbp+30h],edi 
00000001401A6964  mov         dword ptr [rbp-0Ch],eax 
    debug_x64_i = _InterlockedOr((long*)&my_uint32_t_var, 0);
00000001401A6967  prefetchw   [rbp+30h] 
00000001401A696B  mov         eax,dword ptr [rbp+30h] 
00000001401A696E  xchg        ax,ax 
00000001401A6970  mov         ecx,eax 
00000001401A6972  lock cmpxchg dword ptr [rbp+30h],ecx 
00000001401A6977  jne         foo+30h (01401A6970h) 
00000001401A6979  mov         dword ptr [rbp-0Ch],eax 
    volatile long release_x64_i = std::atomic_load((const std::_Atomic_long *)&my_uint32_t_var);
00000001401A6955  mov         eax,dword ptr [rbp+30h] 
    release_x64_i = _InterlockedCompareExchange((long*)&my_uint32_t_var, 0, 0);
00000001401A6958  mov         dword ptr [rbp-0Ch],eax 
00000001401A695B  xor         edi,edi 
00000001401A695D  mov         eax,dword ptr [rbp-0Ch] 
00000001401A6960  xor         eax,eax 
00000001401A6962  lock cmpxchg dword ptr [rbp+30h],edi 
00000001401A6967  mov         dword ptr [rbp-0Ch],eax 
    release_x64_i = _InterlockedOr((long*)&my_uint32_t_var, 0);
00000001401A696A  prefetchw   [rbp+30h] 
00000001401A696E  mov         eax,dword ptr [rbp+30h] 
00000001401A6971  mov         ecx,eax 
00000001401A6973  lock cmpxchg dword ptr [rbp+30h],ecx 
00000001401A6978  jne         foo+31h (01401A6971h) 
00000001401A697A  mov         dword ptr [rbp-0Ch],eax

你使用互斥锁的计划(2)是正确的。

好运。