c - 使用编译器内部函数实现自旋锁以同步 OpenMP 线程

标签 c multithreading openmp intrinsics

请查看以下使用 OpenMP 进行并行化的代码片段:

char lock = 0;
#pragma omp parallel
{
    while(!__sync_bool_compare_and_swap(&lock, 0, 1));
    printf("Thread: %d is working!\n", omp_get_thread_num());
    sleep(1);
    printf("Thread: %d unlocks lock!\n", omp_get_thread_num());
    lock = 0;
}

是否有可能线程同时锁定锁,即使锁定是原子的,使用 __sync_bool_compare_and_swap? 例如,并非所有线程都具有一致的内存 View ?

最佳答案

如果您坚持不以 OpenMP 方式执行此操作:

你肯定需要一个编译器屏障来防止 lock=0 成为 reordered at compile time .

如果您只针对 x86,那么只需要一个编译器屏障就可以了;否则使用 C11 atomic_thread_fence(memory_order_release)lock=0 之前,这只是 x86 上的编译器障碍,但会在弱序架构上发出必要的指令。

或者使 lock 成为原子类型,并使用 C11 stdatomic release-store 将其设置为 0。


lock cmpxchg 上自旋来获取锁是非常低效的。您应该在负载上旋转直到锁定可用,然后尝试承受它。例如你应该写一些可以编译成代码的东西 like this minimal but real asm spinlock implementation.

例如使用带有 memory_order_acquire 的 C11 原子加载。然后使用普通的 xchg,而不是 cmpxchg,并检查您是否获得了锁,或者是否有其他线程在您之前获得了它。

关于c - 使用编译器内部函数实现自旋锁以同步 OpenMP 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37994579/

相关文章:

c - 如何计算同时运行的所有子进程的总执行时间?

c++ - D3D9 多线程创建纹理/顶点缓冲区

Clang/LLVM OpenMP 程序不生成线程

c++ - EXP的并行化

c++ - 有什么方法可以强制openmp获得所需的线程数?

c - 在 unp2 书中,为什么 Posix shm 示例会溢出?

c - 在 C 函数中修改数组

c - 如何直接为 vscanf/vprinf 创建一个参数列表?

c++ - Boost::Asio 异步 UDP 服务器 - 未处理的异常消息

c++ - 如何处理线程函数中的重复代码?