如何在C中使用原子变量?

lpp*_*ier 11 c linux atomic

我需要在 C 中使用一个原子变量,因为这个变量是跨不同线程访问的。不想要竞争条件。

我的代码在 CentOS 上运行。我有哪些选择?

Cir*_*四事件 10

C11 原子原语

http://en.cppreference.com/w/c/language/atomic

_Atomic const int * p1;  // p is a pointer to an atomic const int
const atomic_int * p2;   // same
const _Atomic(int) * p3; // same
Run Code Online (Sandbox Code Playgroud)

在 glibc 2.28 中添加。通过从源代码编译 glibc 在 Ubuntu 18.04 (glibc 2.27) 中测试:单个主机上的多个 glibc 库后来也在 Ubuntu 20.04、glibc 2.31 上进行了测试。

示例改编自:https : //en.cppreference.com/w/c/language/atomic

主文件

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

atomic_int acnt;
int cnt;

int f(void* thr_data)
{
    (void)thr_data;
    for(int n = 0; n < 1000; ++n) {
        ++cnt;
        ++acnt;
        // for this example, relaxed memory order is sufficient, e.g.
        // atomic_fetch_add_explicit(&acnt, 1, memory_order_relaxed);
    }
    return 0;
}

int main(void)
{
    thrd_t thr[10];
    for(int n = 0; n < 10; ++n)
        thrd_create(&thr[n], f, NULL);
    for(int n = 0; n < 10; ++n)
        thrd_join(thr[n], NULL);

    printf("The atomic counter is %u\n", acnt);
    printf("The non-atomic counter is %u\n", cnt);
}
Run Code Online (Sandbox Code Playgroud)

编译并运行:

gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c -pthread
./main.out
Run Code Online (Sandbox Code Playgroud)

可能的输出:

The atomic counter is 10000
The non-atomic counter is 8644
Run Code Online (Sandbox Code Playgroud)

由于跨线程访问非原子变量,非原子计数器很可能小于原子计数器。

反汇编分析:如何在普通 C 中启动线程?


jxh*_*jxh 5

如果您在 CentOS 平台上使用 GCC,那么您可以使用__atomic内置函数

特别感兴趣的可能是这个函数:

— 内置函数:bool __atomic_always_lock_free (size_t size, void *ptr)
如果size字节对象总是为目标架构生成无锁原子指令,则该内置函数返回真。size必须解析为编译时常量,结果也解析为编译时常量。

ptr是指向对象的可选指针,可用于确定对齐。值0表示应使用典型对齐方式。编译器也可能会忽略此参数。

      if (_atomic_always_lock_free (sizeof (long long), 0))
Run Code Online (Sandbox Code Playgroud)