use*_*717 8 c++ parallel-processing multithreading atomic c++11
有什么区别
extern std::atomic<int> x;
int i = x++;
和
extern std::atomic<int> x;
int i = x.fetch_add(1);
我觉得第二个版本更安全,但我看不出这两个版本之间的测试有什么不同.
差别绝对不是两种方法都保证的安全性=原子性.
我认为最重要的区别是fetch_add()可以采用不同的内存顺序参数,而对于增量运算符,它总是如此memory_order_seq_cst.
另一个明显的区别是,fetch_add()不仅可以1作为参数,而另一方面,operator++更可能使用lock inc指令实现(尽管理论上没有什么能阻止编译器进行这样的优化fetch_add(1))
所以回答你的确切问题,x++和之间没有任何语义上的重要区别x.fetch_add(1).该医生说:
此函数的行为就像使用1和memory_order_seq_cst作为参数调用atomic :: fetch_add一样.
x.fetch_add(1)和x++完全相同std::atomic
如果您相信 cppreference,https://en.cppreference.com/w/cpp/atomic/atomic/operator_arith说:
Run Code Online (Sandbox Code Playgroud)T operator++() volatile noexcept; (1) T* operator++() volatile noexcept; (2)
执行原子预增量。相当于
fetch_add(1)+1。
执行原子后递增。相当于
fetch_add(1)。
https://en.cppreference.com/w/cpp/atomic/atomic/fetch_add然后文档:
T fetch_add( T arg, std::memory_order order = std::memory_order_seq_cst ) noexcept;
所以我们看到 ofstd::memory_order默认operator++为std::memory_order_seq_cst,这是可用的更强的,另请参阅:每个内存顺序是什么意思?
C++11 标准引号
如果您不相信 cppreference,C++11 N3337 草案29.6.5/33“原子类型操作的要求”说:
Run Code Online (Sandbox Code Playgroud)C A ::operator++(int) volatile noexcept; C A ::operator++(int) noexcept;返回: fetch_add(1)
29.6.5/2 澄清C并A:
- A 指原子类型之一。
- a C 指的是其对应的非原子类型
我无法找到明确的解释,但我想Returns: fetch_add(1)这意味着fetch_add(1)当然是因为它的副作用。
还值得进一步研究一下前缀版本:
Run Code Online (Sandbox Code Playgroud)C A ::operator++() volatile noexcept; C A ::operator++() noexcept;效果:fetch_add(1)
返回: fetch_add(1) + 1
这表明这个返回值+1,就像整数的常规前缀增量一样。
海湾合作委员会4.8
libstdc++-v3/include/std/atomic说atomic<int>继承__atomic_base<int>:
struct atomic<int> : __atomic_base<int>
libstdc++-v3/include/bits/atomic_base.h的实现如下:
__int_type
operator++(int) noexcept
{ return fetch_add(1); }
__int_type
operator++(int) volatile noexcept
{ return fetch_add(1); }
__int_type
operator++() noexcept
{ return __atomic_add_fetch(&_M_i, 1, memory_order_seq_cst); }
__int_type
operator++() volatile noexcept
{ return __atomic_add_fetch(&_M_i, 1, memory_order_seq_cst); }
_GLIBCXX_ALWAYS_INLINE __int_type
fetch_add(__int_type __i,
memory_order __m = memory_order_seq_cst) noexcept
{ return __atomic_fetch_add(&_M_i, __i, __m); }
_GLIBCXX_ALWAYS_INLINE __int_type
fetch_add(__int_type __i,
memory_order __m = memory_order_seq_cst) volatile noexcept
{ return __atomic_fetch_add(&_M_i, __i, __m); }
我不明白为什么后缀调用fetch_add助手而前缀直接使用内置函数,但最终它们都归结为 GCC 内在函数__atomic_fetch_add,并__atomic_add_fetch真正起作用。
| 归档时间: | 
 | 
| 查看次数: | 3825 次 | 
| 最近记录: |