当前位置: C语言 -- 标准库 -- <stdatomic.h> -- atomic_thread_fence

atomic_thread_fence函数


概要:
#include <stdatomic.h>
void atomic_thread_fence(memory_order order);

描述:

栅栏(fence)是没有关联内存位置的同步操作。一个栅栏可以是获取栅栏、释放栅栏或者同时是获取和释放栅栏。ISO/IEC 9899:2018标准第7.17.4 Fences节定义了与栅栏同步的三种形式:

1、释放栅栏和获取栅栏的同步

假设存在一个释放栅栏A、一个获取栅栏B和两个原子操作XYXY都是对某个原子对象M进行操作;A排序先于(sequenced beforeXY排序先于(sequenced beforeBX修改MY读取X写入的值或者以释放操作X为首的释放序列(release sequence)的任何副作用写入的值;这种情况下释放栅栏A与获取栅栏B同步,A之前的所有写操作B之后可见,例如:

atomic_int M = 0;

/*线程一。*/
...         //其它操作。
atomic_thread_fence(memory_order_release);              //A
atomic_store_explicit(&M, 10, memory_order_relaxed);    //X

/*线程二。*/
while(!atomic_load_explicit(&M, memory_order_relaxed))  //Y
    ;
atomic_thread_fence(memory_order_acquire);              //B
...         //其它操作。

2、释放栅栏和原子获取操作的同步

假设存在一个释放栅栏A和两个原子操作XY,其中Y对原子对象M进行获取操作;A排序先于(sequenced beforeXX修改MY读取X写入的值或者以释放操作X为首的释放序列(release sequence)的任何副作用写入的值;这种情况下释放栅栏A与原子获取操作Y同步,A之前的所有写操作Y之后可见,例如:

atomic_int M = 0;

/*线程一。*/
...         //其它操作。
atomic_thread_fence(memory_order_release);              //A
atomic_store_explicit(&M, 10, memory_order_relaxed);    //X

/*线程二。*/
while(!atomic_load_explicit(&M, memory_order_acquire))  //Y
    ;
...         //其它操作。

3、原子释放操作和获取栅栏的同步

假设存在一个获取栅栏B和两个原子操作XY,其中X对原子对象M进行释放操作;Y排序先于(sequenced beforeBY读取X写入的值或者以释放操作X为首的释放序列(release sequence)的任何副作用写入的值;这种情况下释放操作X与获取栅栏B同步,X之前的所有写操作B之后可见,例如:

atomic_int M = 0;

/*线程一。*/
...         //其它操作。
atomic_store_explicit(&M, 10, memory_order_release);    //X

/*线程二。*/
while(!atomic_load_explicit(&M, memory_order_relaxed))  //Y
    ;
atomic_thread_fence(memory_order_acquire);              //B
...         //其它操作。

该函数具体操作取决于参数order的值:

- 如果参数order的值是memory_order_relaxed,操作不起任何作用;

- 如果参数order的值是memory_order_acquire或者memory_order_consume,操作是一个获取栅栏。

- 如果参数order的值是memory_order_release,操作是一个释放栅栏。

- 如果参数order的值是memory_order_acq_rel,操作既是一个获取栅栏,也是一个释放栅栏。

- 如果参数order的值是memory_order_seq_cst,操作是一个顺序一致的获取和释放栅栏。


参数:
memory_order order

枚举常量,显式地指定内存顺序。


返回值:

无。


范例:
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 
54 
55 
56 
57 
58 
59 
60 
61 
62 
63 
64 
/*函数atomic_thread_fence范例*/

#ifdef __STDC_NO_ATOMICS__
#error "Implementation does not support atomic types."
#endif

#ifdef __STDC_NO_THREADS__
#error "Implementation does not support multi-threads."
#endif

#include <assert.h>
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <threads.h>

#define THREAD 2

atomic_int aNumber = 0;
int number = 0;

/*线程一中执行的函数。*/
int funcOne(void *arg)
{
    number = 5;
    atomic_thread_fence(memory_order_release);
    atomic_store_explicit(&aNumber, 15, memory_order_relaxed);
    
    thrd_exit(0);
}

/*线程二中执行的函数。*/
int funcTwo(void *arg)
{
    while(!atomic_load_explicit(&aNumber, memory_order_acquire))
        ;
    
    assert(number==5);

    thrd_exit(0);
}

int main(void)
{
    thrd_t threadId[THREAD];

    if(thrd_create(&threadId[0], funcOne, NULL) != thrd_success)
    {
        perror("thrd_create error");
        exit(EXIT_FAILURE);
    }
    
    if(thrd_create(&threadId[1], funcTwo, NULL) != thrd_success)
    {
        perror("thrd_create error");
        exit(EXIT_FAILURE);
    } 

    thrd_join(threadId[0], NULL);
    thrd_join(threadId[1], NULL);
    
    return 0;
}


结果:

线程二中的断言assert(number==5)不可能触发。

注:使用Pelles C编译。


相关内容:
atomic_signal_fence 原子信号栅栏函数。