当前位置: 首页 > 工具软件 > Atomic > 使用案例 >

原子操作__atomic_store and __atomic_load

上官自明
2023-12-01

链接: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)。

atomic_store:

在头文件<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,第二个版本根据内存访问内存访问orderorder必须是其中的一个memory_order_relaxedmemory_order_release或者memory_order_seq_cst。否则,行为是不确定的。

这是为所有原子对象类型定义的通用函数A。该参数是指向易失性原子类型的指针,以接受非易失性和易失性(例如内存映射I/O)原子变量的地址。C是与之对应的非原子类型A

参数

obj

-

指向要修改的原子对象的指针

order

-

此操作的内存同步排序

返回值

(none).

参考

  • C11标准(ISO/IEC 9899:2011):
    • 7.17.7.1 atomic_store通用函数(p: 282)

另请参阅

//----------------------------------------------------------------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;
}

//=============================================================================//

gcc与clang内置原子操作函数:

原子操作在实现多线程并发操作时非常重要的功能。

在现有的线程库中,一般通过提供锁的功能实现线程的互斥与同步。

但是锁的粒度比较大,在性能要求非常高的软件中可能会受限制。

原子操作函数则能在最小粒度上实现并发的互斥与同步,很多的无锁数据结构(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不相同,使用的时候需要注意。

 类似资料: