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!"); } }
参考:
1、C语言原子操作