我正在寻找一种原子地增加短路的方法,然后返回该值。我需要在内核模式和用户模式下执行此操作,因此它在C语言下,在Linux下,在Intel 32位架构上。不幸的是,由于速度要求,互斥锁不是一个好的选择。
还有其他办法吗?在这一点上,似乎唯一可用的选项是内联一些程序集。如果是这种情况,有人可以指出我适当的指示吗?
答案 0 :(得分:8)
GCC __atomic_*
内置插件
自GCC 4.8起,__sync
内置版已弃用,以支持__atomic
内置插件:https://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/_005f_005fatomic-Builtins.html
他们实现了C ++内存模型,std::atomic
在内部使用它们。
以下POSIX线程示例在x86-64上与++
一致失败,并始终与_atomic_fetch_add
一起使用。
的main.c
#include <assert.h>
#include <pthread.h>
#include <stdlib.h>
enum CONSTANTS {
NUM_THREADS = 1000,
NUM_ITERS = 1000
};
int global = 0;
void* main_thread(void *arg) {
int i;
for (i = 0; i < NUM_ITERS; ++i) {
__atomic_fetch_add(&global, 1, __ATOMIC_SEQ_CST);
/* This fails consistently. */
/*global++*/;
}
return NULL;
}
int main(void) {
int i;
pthread_t threads[NUM_THREADS];
for (i = 0; i < NUM_THREADS; ++i)
pthread_create(&threads[i], NULL, main_thread, NULL);
for (i = 0; i < NUM_THREADS; ++i)
pthread_join(threads[i], NULL);
assert(global == NUM_THREADS * NUM_ITERS);
return EXIT_SUCCESS;
}
编译并运行:
gcc -std=c99 -Wall -Wextra -pedantic -o main.out ./main.c -pthread
./main.out
反汇编分析:How do I start threads in plain C?
在Ubuntu 18.10,GCC 8.2.0,glibc 2.28中进行了测试。
C11 _Atomic
在5.1中,上面的代码适用于:
_Atomic int global = 0;
global++;
在glibc 2.28中添加了C11 threads.h
,它允许您在没有POSIX的纯ANSI C中创建线程,最小可运行示例:How do I start threads in plain C?
答案 1 :(得分:7)
GCC支持原子操作: