我正在尝试实现比较和交换操作,以便我的线程基于值u_parent
知道是否要进入特定区域。我只想知道这是否是实现它的正确方法,以及我是否在某处出错。
int *u_parent;
u_parent = &graph->parents[u];
if (*u_parent < 0) {
// This region should only be entered by each thread
// if the value of u_parent is < -1.
graph->parents[u] = v;
// ^-- If region is entered, this value is modified
// by some variable v
//Swap:
u_parent = &graph->parents[u];
DO_SOMETHING();
}
此实现是否正确,因为在执行CAS操作后仍然看到其他线程进入该区域?
答案 0 :(得分:4)
我正在尝试执行比较和交换操作
您不能在C语言中实现该操作。必须进行atomic这样的操作才能有意义地用于线程之间的同步。请注意sequence points和memory models。
某些编译器为此提供了一个内置函数。 (另请参阅this问题)。最近的GCC提供了atomic builtins,其中包括__atomic_compare_exchange
,这些 implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1'
通常被编译成单个机器代码指令。阅读compare-and-swap
在Linux上,还要注意futex(7)。使用CMPXCHG之类的机器指令,它们是许多pthreads(7)操作的构造块(因此需要一些汇编代码)。另请阅读优质的pthread tutorial。 C11标准(读为n1570)提供了<stdatomic.h>
(实际上,标准的原子操作内置于编译器中,或使用现有的内置物)。
还要研究现有free software C标准库的源代码,例如GNU glibc或musl-libc。您会看到许多同步原语是在futex,汇编代码和/或编译器内置文件之上构建的。
此外,OpenMP(由编译器实现时)正在改变编译器(当然还有生成的可执行文件)的行为。