【问题标题】:Does as-if rule allow this kind of execution reorderingas-if 规则是否允许这种执行重新排序
【发布时间】:2021-03-24 02:32:31
【问题描述】:

正如我们所知,编译器或 CPU 可以根据需要重新排序执行,前提是它们遵循 as-if 规则。例如,如果我们有这样一段代码:

C = A + B;
D = E + F;

编译器或 CPU 可能会在 C = A + B 之前执行 D = E + F。我能理解。

现在让我们谈谈另一个案例。

说我有两个线程ab。我想在执行时设置一些标记,以便我可以监控ab的整个过程。

queue q; // thread safe

void thread_a()
{
    // do something
    q.push("a - 1");
    // do something
    q.push("a - 2");
}

void thread_b()
{
    // do something
    q.push("b - 1");
    // do something
    q.push("b - 2");
}

我的问题是:既然我们有as-if规则并且执行顺序可能会重新排序,那是否意味着q中的消息不可靠?这意味着真正的执行顺序是a - 1b - 1b - 2a - 2 但在q 中可能有a - 1a - 2b - 1b - 2?如果发生这种情况,我应该如何设计或使用哪种技术来监控多线程的进程?

【问题讨论】:

  • 只是为了检查:你说queue q; 是线程安全的。你知道std::queue is not thread safe,对吧?使用锁定(或无锁原子)的实际线程安全队列几乎肯定会强制执行排序约束(至少是获取/释放语义),这会抑制任意重新排序。
  • 我有点怀疑两个推送都可以以这种方式重新排序。你能举一个这样的小说的例子吗queue这是真的吗?
  • @SamVarshavchik 这有关系吗?确实存在一些线程安全队列,对吧?或者我们可以在这两个函数中使用互斥锁。您是在告诉我这两个函数中的线程安全队列或互斥锁会禁止重新排序吗?
  • 如果队列不是线程安全的,那么另一个线程可以观察到没有条目的大小为 2 的队列。或者只有两个条目之一。
  • 您需要定义real execution order 是什么。给定示例中的源代码行都不是原子操作(even 在线程安全实现中)。完全有可能在q.push("a - 1"); 开始之前执行到q.push("b - 1");,但在结束后返回。

标签: c++ multithreading c++11 instruction-reordering as-if


【解决方案1】:

重新排序和多线程是两个不同的东西:

通过多线程,可能的输出是:

  • "a - 1", "a - 2", "b - 1", "b - 2"
  • "a - 1", "b - 1", "a - 2", "b - 2"
  • "a - 1", "b - 1", "b - 2", "a - 2"
  • "b - 1", "b - 2", "a - 1", "a - 2"
  • "b - 1", "a - 1", "b - 2", "a - 2"
  • "b - 1", "a - 1", "a - 2", "b - 2"

您只需保证“a - 1”在“a - 2”之前,“b - 1”在“b - 2”之前。 (与重新排序无关)

使用 as-if 规则重新排序只是一种优化。

as_if 状态:

只要满足以下条件,C++ 编译器就可以对程序进行任何更改:

  1. 对易失性对象的访问(读取和写入)严格按照它们出现的表达式的语义进行。特别是,它们不会针对同一线程上的其他易失性访问重新排序。 (C++11 起)
  2. 在程序终止时,写入文件的数据与程序执行时完全一样。
  3. 发送到交互式设备的提示文本将在程序等待输入之前显示。
  4. 如果支持 ISO C pragma #pragma STDC FENV_ACCESS 并将其设置为 ON,则浮点算术运算符和函数调用就像按书面执行一样,除了 除强制转换和赋值之外的任何浮点表达式的结果可能具有与表达式类型不同的浮点类型的范围和精度(请参阅 FLT_EVAL_METHOD) 尽管有上述规定,任何浮点表达式的中间结果都可以计算为无限范围和精度(除非 #pragma STDC FP_CONTRACT 为 OFF)

您的代码(可能是 // do something 除外)对此没有任何作用,因此它甚至可以完全删除 2 代码,按下“c - 1”。

但是如果你打印队列内容后,那么内容应该是上面显示的6个之一。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-16
    • 2018-05-20
    • 2013-01-18
    相关资源
    最近更新 更多