以原子方式读取值的函数?

时间:2016-07-05 11:28:43

标签: c++ multithreading

我正在玩原子读写,并且在我的理解中遇到了障碍。我理解写入变量(例如通过增量)必须是原子的,但我不确定读取变量。

在Windows上考虑_InterlockedExchangeAdd,在Linux上考虑__sync_add_and_fetch。我找不到一个原子检索正在更新的值的函数。现在我在发布之前完成了我的研究,Are C++ Reads and Writes of an int Atomic?告诉我,读取不是原子。

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

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

修改

我使用的编译器无法访问原子头,因此必须使用这些API。

1 个答案:

答案 0 :(得分:1)

你无法找到答案,因为没有一种方法可以做到这一点,因为它是(a)快速和(b)便携式。它取决于:C ++或C,编译器,编译器版本,编译器设置,库,架构......列表一直在继续。

这是一个起点:

我碰巧有一个汇编代码片段,可以解释为什么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)是正确的。

祝你好运。