链接:https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
https://blog.csdn.net/weixin_36145588/article/details/73847365
http://www.verydoc.net/c/00000145.html
原子操作在多线程开发中经常用到,比如在计数器,序列产生器等地方,这类情况下数据有并发的危险,但是用锁去保护又显得有些浪费,所以原子类型操作十分的方便。
原子操作虽然用起来简单,但是其背景远比我们想象的要复杂。其主要在于现代计算系统过于的复杂:多处理器、多核处理器、处理器又有核心独有以及核心共享的多级缓存,在这种情况下,一个核心修改了某个变量,其他核心什么时候可见是一个十分严肃的问题。同时在极致最求性能的时代,处理器和编译器往往表现的很智能,进行极度的优化,比如什么乱序执行、指令重排等,虽然可以在当前上下文中做到很好的优化,但是放在多核环境下常常会引出新的问题来,这时候就必须提示编译器和处理器某种提示,告诉某些代码的执行顺序不能被优化。
所以这里说到的原子操作,基本都包含我们三个方面所关心的语义:操作本身是不可分割的(Atomicity),一个线程对某个数据的操作何时对另外一个线程可见(Visibility),执行的顺序是否可以被重排(Ordering)。
在头文件<stdatomic.h>中定义 | | |
---|---|---|
void atomic_store(volatile A * obj,需要C); | (1) | (自C11以来) |
void atomic_store_explicit(volatile A * obj,C desired,memory_order order); | (2) | (自C11以来) |
原子替换obj
指向的原子变量的值desired
。该操作是原子写入操作。
第一个版本根据命令对内存进行访问memory_order_seq_cst
,第二个版本根据内存访问内存访问order
。order
必须是其中的一个memory_order_relaxed
,memory_order_release
或者memory_order_seq_cst
。否则,行为是不确定的。
这是为所有原子对象类型定义的通用函数A
。该参数是指向易失性原子类型的指针,以接受非易失性和易失性(例如内存映射I/O)原子变量的地址。C
是与之对应的非原子类型A
。
obj | - | 指向要修改的原子对象的指针 |
---|---|---|
order | - | 此操作的内存同步排序 |
(none).
//----------------------------------------------------------------demo-------------------------------------------//
#include <stdio.h>
#include <string.h>
int atomic_tst()
{
char arr[64] = "hello";
char bb[62] = "word";
char *p = NULL;
int q = 0;
int c = 128;
int *d = &c;
/*
store release(__ATOMIC_RELEASE), load acquire(__ATOMIC_ACQUIRE) 成对使用
指针赋值时用__atomic_store_n, __atomic_load
整数赋值时使用 __atomic_store/__atomic_store_n, __atomic_load_n
*/
/*
Built-in Function: void __atomic_store_n (type *ptr, type val, int memorder)
This built-in function implements an atomic store operation. It writes val into *ptr.
The valid memory order variants are __ATOMIC_RELAXED, __ATOMIC_SEQ_CST, and __ATOMIC_RELEASE.
将 val 值加载到 ptr指向的地址
*/
// 两个都是指针时效果等于 p = arr
__atomic_store_n(&p, &arr, __ATOMIC_RELEASE);//<<==>> p = arr
//__atomic_store_n(&p, 0, __ATOMIC_RELEASE); <<==> p = NULL;等于指针置空
printf("%s\n", p);//hello
/*
Built-in Function: void __atomic_store (type *ptr, type *val, int memorder)
This is the generic version of an atomic store. It stores the value of *val into *ptr.
将 val 指向地址的内容加载到 prt 指向的地址
*/
// 指针地址单个赋值 *p = bb[0]
__atomic_store(p, bb, __ATOMIC_RELEASE);
printf("%s\n", p);//wello
//对整形数值赋值
__atomic_store(&q, &c, __ATOMIC_RELEASE);// <<==>> q = c
printf("%d\n", q);//128
__atomic_store(&q, d, __ATOMIC_RELEASE);
printf("%d\n", q);//128
/*
Built-in Function: void __atomic_load (type *ptr, type *ret, int memorder)
This is the generic version of an atomic load. It returns the contents of *ptr in *ret.
将 ptr 指向的地址内容 加载到 ret 指向的地址
*/
q = 11;
*d = 22;
__atomic_load(&q, d, __ATOMIC_ACQUIRE);
printf("q = %d, d = %d\n", q, *d); //q = 11, d = 11
*d = 66;
/*
Built-in Function: type __atomic_load_n (type *ptr, int memorder)
This built-in function implements an atomic load operation. It returns the contents of *ptr.
The valid memory order variants are __ATOMIC_RELAXED, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE, and __ATOMIC_CONSUME.
返回 ptr指向的值
*/
q =__atomic_load_n(d, __ATOMIC_ACQUIRE);
printf("q = %d, d = %d\n", q, *d); //q = 66, d = 66
return 0;
}
//=============================================================================//
原子操作在实现多线程并发操作时非常重要的功能。
在现有的线程库中,一般通过提供锁的功能实现线程的互斥与同步。
但是锁的粒度比较大,在性能要求非常高的软件中可能会受限制。
原子操作函数则能在最小粒度上实现并发的互斥与同步,很多的无锁数据结构(lock-free data structure)库皆使用这些函数实现的。
不同的编译器提供的原子操作函数不相同,但总结下来,也就几种模式,包括:
*)原子加、减并返回操作结果,或者返回当前值后再加、减
*)原子与、或、异或并返回操作结果,或者返回当前值后再与、或、异或
*) test and set类功能,测试标识并设置相应的值
*) exchange/swap类功能,比较并交换值
*)
目前最新版本的gcc、clang的原子操作实现均符合c++11定义的原子操作6种内存模型:
__ATOMIC_RELAXED No barriers or synchronization.
__ATOMIC_CONSUME Data dependency only for both barrier and synchronization with another thread.
__ATOMIC_ACQUIRE Barrier to hoisting of code and synchronizes with release (or stronger) semantic stores from another thread.
__ATOMIC_RELEASE Barrier to sinking of code and synchronizes with acquire (or stronger) semantic loads from another thread.
__ATOMIC_ACQ_REL Full barrier in both directions and synchronizes with acquire loads and release stores in another thread.
__ATOMIC_SEQ_CST Full barrier in both directions and synchronizes with acquire loads and release stores in all threads.
详见 http://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync
gcc的内置原子函数:
定义见 http://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
定义列表:
— Built-in Function: type __atomic_load_n (type *ptr, int memmodel)
— Built-in Function: void __atomic_load (type *ptr, type *ret, int memmodel)
— Built-in Function: void __atomic_store_n (type *ptr, type val, int memmodel)
— Built-in Function: void __atomic_store (type *ptr, type *val, int memmodel)
— Built-in Function: type __atomic_exchange_n (type *ptr, type val, int memmodel)
— Built-in Function: void __atomic_exchange (type *ptr, type *val, type *ret, int memmodel)
— Built-in Function: bool __atomic_compare_exchange_n (type *ptr, type *expected, type desired, bool weak, int success_memmodel, int failure_memmodel)
— Built-in Function: bool __atomic_compare_exchange (type *ptr, type *expected, type *desired, bool
— Built-in Function: type __atomic_add_fetch (type *ptr, type val, int memmodel)
— Built-in Function: type __atomic_sub_fetch (type *ptr, type val, int memmodel)
— Built-in Function: type __atomic_and_fetch (type *ptr, type val, int memmodel)
— Built-in Function: type __atomic_xor_fetch (type *ptr, type val, int memmodel)
— Built-in Function: type __atomic_or_fetch (type *ptr, type val, int memmodel)
— Built-in Function: type __atomic_nand_fetch (type *ptr, type val, int memmodel)
— Built-in Function: type __atomic_fetch_add (type *ptr, type val, int memmodel)
— Built-in Function: type __atomic_fetch_sub (type *ptr, type val, int memmodel)
— Built-in Function: type __atomic_fetch_and (type *ptr, type val, int memmodel)
— Built-in Function: type __atomic_fetch_xor (type *ptr, type val, int memmodel)
— Built-in Function: type __atomic_fetch_or (type *ptr, type val, int memmodel)
— Built-in Function: type __atomic_fetch_nand (type *ptr, type val, int memmodel)
— Built-in Function: bool __atomic_test_and_set (void *ptr, int memmodel)
— Built-in Function: void __atomic_clear (bool *ptr, int memmodel)
— Built-in Function: void __atomic_thread_fence (int memmodel)
— Built-in Function: void __atomic_signal_fence (int memmodel)
— Built-in Function: bool __atomic_always_lock_free (size_t size, void *ptr)
— Built-in Function: bool __atomic_is_lock_free (size_t size, void *ptr)
clang的内置原子函数:
定义见 /usr/include/clang/Basic/Builtins.def
另外,c11标准与c++11标准也定义了原子操作的相关规范,
clang与gcc均实现了std::atomic模板类,实现更高级的原子操作实现,在实例用上相同的。
但两者实现的_Atomic和_Atomic_word不相同,使用的时候需要注意。