我正在玩原子读写,并且在我的理解中遇到了障碍。我理解写入变量(例如通过增量)必须是原子的,但我不确定读取变量。
在Windows上考虑_InterlockedExchangeAdd
,在Linux上考虑__sync_add_and_fetch
。我找不到一个原子检索正在更新的值的函数。现在我在发布之前完成了我的研究,Are C++ Reads and Writes of an int Atomic?告诉我,读取不是原子。
1)如果我使用上面的函数,我如何原子地读取值,比如从函数返回它?
2)如果我不想使用这些功能,只想在每次写入" atomic"之前锁定一个互斥锁。变量,在检索变量当前值的函数中,我需要先锁定互斥锁,复制当前值,解锁互斥锁然后返回副本吗?
修改
我使用的编译器无法访问原子头,因此必须使用这些API。
答案 0 :(得分:1)
你无法找到答案,因为没有一种方法可以做到这一点,因为它是(a)快速和(b)便携式。它取决于:C ++或C,编译器,编译器版本,编译器设置,库,架构......列表一直在继续。
这是一个起点:
atomic_load()
- 它便携且快速。_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,Microsoft编译器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)是正确的。
祝你好运。