给定此伪代码,全局存在一个原子int a
初始化为0:
线程1:
// ... some code here (X) ...
a.store(1, relaxed);
futex_wake(&a);
线程2:
if (futex_wait(&a, 1) == woken_up) {
assert(a.load(relaxed) == 1);
// ... some code here (Y) ...
}
不理会虚假唤醒的可能性; 我们可以从上面的代码中推断出
X
与Y
同步吗? 基本上,它可以归结为futex本身是否旨在在唤醒的等待中实现获取/释放语义。有一点上下文:TSAN无法理解futex系统调用(例如,参见here,here)。
现在,通常,当使用futex来实现互斥量,信号量或其他某种同步原语时,它还具有一个原子变量,该原子变量通过“锁定”侧装入获取顺序,并通过“解锁”存储在释放顺序中边。 (以上,我故意使用宽松的语义。)
获取/释放足以实现同步,在形式上是正确的,并且被TSAN识别(对于以这种方式实现的锁,它不报告任何内容,例如Qt中的QBasicMutex)。
这个问题主要是关于论坛帖子linked above中提供的关于使用获取/释放语义来标记futex操作本身的建议。 这样的标记正确吗?
(我知道C++抽象机对
futex
一无所知。它甚至对pthreads也一无所知,但是TSAN知道。对于在pthread_create
之前发生的代码也在在新创建的线程中运行的代码之前也发生了。换句话说,这不是语言律师的问题...) 最佳答案
从 man futex(2)
:
总排序对应于C++ std::memory_order_seq_cst
:
换句话说,futex
syscall在内核中的作用等同于C++ 11:
a.compare_exchange_strong(..., std::memory_order_seq_cst, std::memory_order_seq_cst);