代码之家  ›  专栏  ›  技术社区  ›  dmeister

UNIX可移植原子操作

  •  28
  • dmeister  · 技术社区  · 15 年前

    对于原子变量操作,C中是否有一种(POSIX-)可移植的方式,类似于使用pthread的可移植线程?

    atomic_t 类型,在Java中我们有 java.util.concurrent.atomic 包裹

    在Linux上,atomic.h文件提供原子操作,但include依赖于平台,例如。 #include <asm-x86_64/atomic.h> 在MacOSX上也没有类似的方式。

    7 回复  |  直到 15 年前
        1
  •  14
  •   user3033869    11 年前

    对于将来偶然发现这一点的人来说,C11原子是现在实现这一点的最佳方式——我相信它们将被纳入GCC 4.9。

        2
  •  14
  •   AG1    7 年前

    从C11开始,有一个可选的 Atomic library

    __STDC_NO_ATOMICS__ 以及 <stdatomic.h>

    原子能

    #include <stdio.h>
    #include <stdlib.h>
    #ifndef __STDC_NO_ATOMICS__
    #include <stdatomic.h>
    #endif
    
    int main(int argc, char**argv) {
        _Atomic int a;
        atomic_init(&a, 42);
        atomic_store(&a, 5);
        int b = atomic_load(&a);
        printf("b = %i\n", b);
    
        return EXIT_SUCCESS;
    }
    

    编译器调用

    clang -std=c11 atomic.c
    gcc -std=c11 atomic.c
    
        3
  •  10
  •   someGuy    14 年前

    OSX具有多种功能 Osatomicad32() 看见 The Threading Programming guide “使用原子操作”一节。

    而对于Windows,则有

    与gcc内置组件一起 __同步获取和添加() 和朋友(已在上面链接),您应该

    请注意,我自己还没有使用它们,但可能会在未来几天内这样做。

        4
  •  4
  •   paxdiablo    15 年前

    否,POSIX没有指定 任何

    你要么不得不使用非标准方式,要么坚持使用ptrheads以实现可移植性。

        5
  •  3
  •   Ciro Santilli OurBigBook.com    5 年前

    通过在Glibc2.28中添加线程,我们可以在纯C11中同时执行原子和线程。

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

    main.c

    #include <stdio.h>
    #include <threads.h>
    #include <stdatomic.h>
    
    atomic_int acnt;
    int cnt;
    
    int f(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);
    }
    

    编译并运行:

    gcc -std=c11 main.c -pthread
    ./a.out
    

    可能的产出:

    The atomic counter is 10000
    The non-atomic counter is 8644
    

    由于线程间对非原子变量的快速访问,非原子计数器很可能比原子计数器小。

    pthreads示例可在以下位置找到: How do I start threads in plain C?

    在Ubuntu 18.04(glibc 2.27)中通过从源代码编译glibc进行测试: Multiple glibc libraries on a single host Ubuntu18.10有Glibc2.28,所以应该在那里工作。

        6
  •  0
  •   Goz    15 年前

    AFAIK没有跨平台的方法来进行原子操作。那里可能有图书馆,但我不知道。不过,自己动手并不特别难。

        7
  •  0
  •   unwind    15 年前

    我想没有。

    当然,许可证允许的情况下,解决这个问题的一种方法是从Linux内核空间复制相关的每体系结构实现。我没有密切关注这些原语的发展,但我猜它们确实是原语,即不依赖内核中的其他服务或API。