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

时间:2016-06-23 14:29:56

标签: 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锁定是原子的? 例如,并非所有线程都具有一致的内存视图?

1 个答案:

答案 0 :(得分:3)

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

您肯定需要编译器屏障来阻止lock=0成为reordered at compile time

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

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

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

的东西

e.g。使用memory_order_acquire的C11原子载荷。然后使用普通xchg,而不是cmpxchg,并检查您是否获得了锁定,或者在您执行此操作之前是否有其他线程接受了锁定。