介绍
Gcc 4.1.2版本之后,对X86或X86_64支持内置原子操作。就是说,不需要引入第三方库(如pthread)的锁保护,即可对1、2、4、8字节的数值或指针类型,进行原子加/减/与/或/异或等操作。
接口介绍
接口 | 说明 |
---|---|
__sync_synchronize | 内存访问栅,确保所有对内存的操作都完成,防止乱序执行 |
__sync_fetch_and_add(ptr, 0) | 原子获取操作,获取指针 ptr 指向的内存值 |
__sync_lock_test_and_set((ptr), (value)) | 原子设置操作,如果原值和新值不一样,则设置新值 |
((typeof(*(ptr)))__sync_lock_test_and_set((ptr), (value))) | 原子交换操作,如果被设置,则返回旧值,否则返回设置值 |
((typeof(*(ptr)))__sync_val_compare_and_swap((ptr), (comp), (value))) | 原子比较交换操作,如果当前值等于旧值,则设置新值,并返回旧值,否则返回新值 |
(__sync_bool_compare_and_swap((ptr), (comp), (value)) != 0 ? true : false) | 原子比较交换操作,如果当前值等于旧值,则设置新值,返回真值,否则返回假 |
((void)__sync_lock_release((ptr))) | 原子清零操作,将指针 ptr 指向的内存值设置为0 |
((typeof(*(ptr)))__sync_add_and_fetch((ptr), (value))) | 算数运算加value,返回新值 |
((typeof(*(ptr)))__sync_sub_and_fetch((ptr), (value))) | 算数运算减value,返回新值 |
((typeof(*(ptr)))__sync_or_and_fetch((ptr), (value))) | 算数运算与value相或,返回新值 |
((typeof(*(ptr)))__sync_and_and_fetch((ptr), (value))) | 算数运算与value相与,返回新值 |
((typeof(*(ptr)))__sync_xor_and_fetch((ptr), (value))) | 算数运算与value相异或,返回新值 |
((typeof(*(ptr)))__sync_fetch_and_add((ptr), (value))) | 算数运算加value,返回减之前的值 |
((typeof(*(ptr)))__sync_fetch_and_sub((ptr), (value))) | 算数运算减value,返回减之前的值 |
((typeof(*(ptr)))__sync_fetch_and_or((ptr), (value))) | 算数运算与value相或,返回操作之前的值 |
((typeof(*(ptr)))__sync_fetch_and_and((ptr), (value))) | 算数运算与value相与,返回操作之前的值 |
((typeof(*(ptr)))__sync_fetch_and_xor((ptr), (value))) | 算数运算与value相异或,返回操作之前的值 |
((void)xrte_atomic_add_f((ptr), 1)) | 原子递增操作,将指针 ptr 指向的内存值加1 |
((void)xrte_atomic_sub_f((ptr), 1)) | 原子递减操作,将指针 ptr 指向的内存值减1 |
((void)xrte_atomic_add_f((ptr), (val))) | 原子增加操作,将指针 ptr 指向的内存值增加 val |
((void)xrte_atomic_sub_f((ptr), (val))) | 原子减少操作,将指针 ptr 指向的内存值减少 val |
((void)xrte_atomic_or_f((ptr), (val))) | 原子按位或操作,将指针 ptr 指向的内存值与 val 按位或 |
((void)xrte_atomic_and_f((ptr), (val))) | 原子按位与操作,将指针 ptr 指向的内存值与 val 按位与 |
((void)xrte_atomic_xor_f((ptr), (val))) | 原子按位异或操作,将指针 ptr 指向的内存值与 val 按位异或 |
例子
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int g_iFlagAtom = 1;
#define WORK_SIZE 5000000
#define WORKER_COUNT 10
pthread_t g_tWorkerID[WORKER_COUNT];
int g_iSum = 0;
void * thr_worker(void *arg) {
printf ("WORKER THREAD %08X STARTUP\n", (unsigned int)pthread_self());
int i=0;
for (i=0; i<WORK_SIZE; ++i) {
if (g_iFlagAtom) {
__sync_fetch_and_add(&g_iSum, 1);
} else {
g_iSum ++;
}
}
return NULL;
}
void * thr_management (void *arg) {
printf ("MANAGEMENT THREAD %08X STARTUP\n", (unsigned int)pthread_self());
int i;
for (i=0;i<WORKER_COUNT;++i) {
pthread_join(g_tWorkerID[i], NULL);
}
printf ("ALL WORKER THREADS FINISHED.\n");
return NULL;
}
int main(int argc, const char* argv[]) {
pthread_t tManagementID;
pthread_create (&tManagementID, NULL, thr_management, NULL);
int i=0;
for (i=0;i<WORKER_COUNT;++i) {
pthread_create(&g_tWorkerID[i], NULL, thr_worker, NULL);
}
printf ("CREATED %d WORKER THREADS\n", i);
pthread_join(tManagementID, NULL);
printf ("THE SUM: %d\n", g_iSum);
return 0;
}
__sync_synchronize
__sync_synchronize是一个GCC内置函数,用于实现同步操作。它的作用是强制对内存的修改操作进行同步,确保所有之前的修改都被提交并对其他线程可见。具体而言, __sync_synchronize
函数会生成一个完整的内存栅栏(memory barrier),防止编译器和处理器对内存操作进行重排或优化。
在多线程编程中, __sync_synchronize
函数通常用于实现原子操作,即确保对共享变量的操作是原子性的、不可分割的。通过在关键位置调用 __sync_synchronize
函数,可以保证线程间的数据同步和一致性。
需要注意的是, __sync_synchronize
函数在C11标准中已被弃用,推荐使用 <stdatomic.h>
头文件中的原子操作函数来替代。
#include <stdio.h>
int shared_var = 0;
void* thread_function(void* arg) {
for (int i = 0; i < 1000000; i++) {
// 在这里进行一些操作,例如递增共享变量
shared_var++;
// 在操作完成后调用 __sync_synchronize 函数进行同步
__sync_synchronize();
}
return NULL;
}
int main() {
pthread_t thread1, thread2;
// 创建两个线程来同时操作共享变量
pthread_create(&thread1, NULL, thread_function, NULL);
pthread_create(&thread2, NULL, thread_function, NULL);
// 等待两个线程结束
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
// 输出最终的共享变量值
printf("shared_var = %d\n", shared_var);
return 0;
}