C语言原子操作

什么是原子类型

用_Atomic(类型名)这种方式修饰的类型是原子类型,在实际使用原子类型时应当避免直接使用_Atomic(类型名)这种形式,而是直接用<stdatomic.h>头文件中已经定义好的原子类型。此外该头文件还有相应的原子操作函数。

常用的原子类型

typedef _Atomic _Bool atomic_bool;
typedef _Atomic char atomic_char;
typedef _Atomic signed char atomic_schar;
typedef _Atomic unsigned char atomic_uchar;
typedef _Atomic short atomic_short;
typedef _Atomic unsigned short atomic_ushort;
typedef _Atomic int atomic_int;
typedef _Atomic unsigned int atomic_uint;
typedef _Atomic long atomic_long;
typedef _Atomic unsigned long atomic_ulong;
typedef _Atomic long long atomic_llong;
typedef _Atomic unsigned long long atomic_ullong;
...

常用的原子操作函数

atomic_init 初始化
atomic_store 赋值
atomic_load 获取
atomic_fetch_add 加
atomic_fetch_sub 减
...

单线程示例

#include <stdio.h>
#include <stdatomic.h>

atomic_int atomic_count = ATOMIC_VAR_INIT(1);

void test()
{
    atomic_int a;
    atomic_init(&a,10);
    int* a_ptr = (int *) &a;
    atomic_store(a_ptr,20);
    int b = atomic_load(a_ptr);
    printf("b = %d\n",b);
    int* atomic_count_ptr = (int *) &atomic_count;
    int atomic_count_old_value = atomic_fetch_add(atomic_count_ptr,b);
    printf("atomic_count_old_value = %d\n",atomic_count_old_value);
    int int_atomic_count = atomic_load(atomic_count_ptr);
    printf("atomic_count = %d\n",int_atomic_count);
}

int main(void)
{
    test();
    return 0;
}

多线程示例

#include <stdio.h>
#include <stdatomic.h>
#include <stdbool.h>
#include <stdint.h>
#include <pthread.h>

static volatile atomic_ullong sAtomResult = ATOMIC_VAR_INIT(0);
static volatile atomic_int sAtomIndex = ATOMIC_VAR_INIT(0);
static volatile uint64_t sNormalResult = 0;
static volatile int sNormalIndex = 0;
static volatile bool sIsThreadComplete = false;
static int sArray[10000][100];

static void* NormalSumProc(void *param) {
    int currIndex;
    while((currIndex = sNormalIndex++) < 10000) {
        uint64_t sum = 0;
        for (int i = 0;i < 100; i++) {
            sum += sArray[currIndex][i];
        }
        sNormalResult += sum;
    }
    sIsThreadComplete = true;
    return NULL;
}

static void* AtomSumProc(void *param) {
    int currIndex;

    while((currIndex = atomic_fetch_add(&sAtomIndex,1))<10000) {
        uint64_t sum = 0;
        for (int i = 0; i < 100; ++i) {
            sum += sArray[currIndex][i];
        }
        atomic_fetch_add(&sAtomResult,sum);
    }
    sIsThreadComplete = true;
    return NULL;
}

int main(int argc,const char* argv[]){
    for (int i = 0; i < 10000; ++i) {
        for (int j = 0; j < 100; ++j) {
            sArray[i][j] = 100 * i + j;
        }
    }
    unsigned long long standardResult = 0;
    for (int i = 0; i < 10000; ++i) {
        for (int j = 0; j < 100; ++j) {
            standardResult += sArray[i][j];
        }
    }
    printf("The standard result is %llu\n",standardResult);

    pthread_t pthreadID;
    pthread_t threadID;
    pthread_create(&threadID,NULL,&NormalSumProc,NULL);

    int currIndex;
    while((currIndex = sNormalIndex++)<10000){
        uint64_t sum = 0;
        for (int i = 0; i < 100; ++i) {
            sum += sArray[currIndex][i];
        }
        sNormalResult += sum;
    }
    while(!sIsThreadComplete);
    if (sNormalResult == standardResult) {
        puts("Normal compute compared equal!");
    } else {
        printf("Normal compute compared not equal: %lu\n",sNormalResult);
    }
    sIsThreadComplete = false;
    pthread_create(&threadID,NULL,&AtomSumProc,NULL);
    while((currIndex = atomic_fetch_add(&sAtomIndex,1))<10000){
        uint64_t sum = 0;
        for (int i = 0; i < 100; ++i) {
            sum += sArray[currIndex][i];
        }
        atomic_fetch_add(&sAtomResult,sum);
    }
    while(!sIsThreadComplete);
    if (atomic_load(&sAtomResult) == standardResult) {
        puts("Atom compute compared equal!");
    } else {
        puts("Atom compute compared not equal!");
    }
}

参考:
posted @ 2016-06-12 16:08  yuxi_o  阅读(438)  评论(0编辑  收藏  举报