c++ - futex 等待/唤醒对是否实现获取/释放语义?

标签 c++ linux multithreading thread-safety futex

给定这个伪代码,全局有一个原子 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) ...
}

忽略虚假唤醒的可能性; 我们是否可以从上面的代码中推导出代码XY同步?归根结底就是futex本身是不是为了实现在被唤醒的等待中获取/释放语义。


一些上下文:TSAN 不理解 futex 系统调用(例如,参见 herehere )。

现在,通常情况下,当使用 futex 来实现互斥量、信号量或其他一些同步原语时,有一个原子变量,该变量通过“锁定”端获取顺序加载,并由“解锁”方存储在发布排序中。 (以上,我故意使用宽松的语义。)

获取/释放足以实现同步,形式上是正确的,并且它被 TSAN 识别(对于以这种方式实现的锁,它不会报告任何内容,例如 Qt 中的 QBasicMutex)。

这个问题主要是关于论坛帖子中提供的建议 linked above用获取/释放语义标记 futex 操作它们自己这样的标记是否正确?

(我知道 C++ 抽象机对 futex 一无所知。它甚至对 pthreads 一无所知,但 TSAN 知道,并且知道例如在 之前发生的代码pthread_create 也发生在新创建的线程中代码运行之前。换句话说,这不是语言律师问题...)

最佳答案

来自 man futex(2) :

The loading of the futex word's value, the comparison of that value with the expected value, and the actual blocking will happen atomically and will be totally ordered with respect to concurrent operations performed by other threads on the same futex word. Thus, the futex word is used to connect the synchronization in user space with the implementation of blocking by the kernel. Analogously to an atomic compare-and-exchange operation that potentially changes shared memory, blocking via a futex is an atomic compare-and-block operation.

总排序对应于 C++ std::memory_order_seq_cst :

A load operation with this memory order performs an acquire operation, a store performs a release operation, and read-modify-write performs both an acquire operation and a release operation, plus a single total order exists in which all threads observe all modifications in the same order.

换句话说,futex 系统调用在内核中相当于 C++11:

a.compare_exchange_strong(..., std::memory_order_seq_cst, std::memory_order_seq_cst);

关于c++ - futex 等待/唤醒对是否实现获取/释放语义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56192182/

相关文章:

c - 如何为 2D 数组设置循环边界以按线程分割工作

c++ - 从超时的 std::future 中检索标识符?

c++ - Cmake 对 `boost::gregorian::greg_month::as_short_string() const' 的 undefined reference

C++ - 正在释放的指针未分配错误

linux - 使用 awk 或 sed 或 cut 过滤文本文件?

c - 如何通过脚本使用cscope来查找定义?

c++ - 如何在 Windows Mobile 中启动互联网连接?

c++ - Win32 GUI 和 C++ 函数的回调

linux - 带有两个输入文件的两个 for 循环 Linux

c# - 如何在迭代中暂停循环