原子内存排序和中断消息循环

时间:2016-10-14 14:16:55

标签: c++ multithreading

考虑以下两个执行线程:

主题A:

// Initialize stuff...
std::atomic<bool> interrupted = false;

// Launch thread B
// ... Do some useful stuff

// Interrupt B
interrupted = true;
InterruptMessageLoop(B);

主题B

RunMessageLoop(); // Can exit by itself or due to InterruptMessageLoop
if (interrupted) {
    // Do something special
}

我的问题是 - 我可以确定,如果线程A确实调用了InterruptMessageLoop,线程B会看到interrupted状态的true原子吗? (我将此称为“期望的行为”)

我在这里看到的问题是,如果我理解正确的话,原始变量的std::memory_order_seq_cst中使用的operator=的内存排序可以保证没有正常的写入将在原子操作之后重新排序,并且在原子操作之前不会重新排序正常的读取 。但是可能会发生线程A在原子之前重新排序InterruptMessageLoop(B),然后线程B中断消息循环并读取interrupted的不正确(关于我想要的逻辑)值,然后只有线程A写入interrupted。那是对的吗?如果是,有没有办法确保我得到我想要的行为而不诉诸互斥量(即将InterruptMessageLoop和布尔修改包装成互斥锁并在读取时锁定相同的互斥锁)?

请注意,我无法控制RunMessageLoop的实施。

修改 请注意,当我发出命令来中断循环并且循环正常存在时(忽略我的命令) - 在我的情况下,线程B认为中断导致消息循环退出是很好的。

1 个答案:

答案 0 :(得分:0)

要准确区分RunMessageLoop是正常完成还是由于InterruptMessageLoop,您必须依赖RunMessageLoop告诉您的某种状态。

你想做的hacky方式是行不通的。假设您设法保证编译器不记录任何内容。您仍然有以下交错:

  • T1:(A)中断=真
  • T2:(B)RunMessageLoop()正常完成。
  • T3:(A)InterruptMessageLoop()
  • T4:(B)if(interrupted)返回true,但B没有被打断!