as-if 规则是否允许这种执行重新排序
Does as-if rule allow this kind of execution reordering
正如我们所知,编译器或 CPU 可能会根据需要重新排序执行,前提是它们遵循 as-if 规则。比如我们有这么一段代码:
C = A + B;
D = E + F;
编译器或 CPU 可能会在 C = A + B
之前执行 D = E + F
。我能理解。
下面说说另外一个案例
说我有两个线程 a
和 b
。我想在执行的时候设置一些标记,这样我就可以监控a
和b
.
的整个过程
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 - 1
、b - 1
、b - 2
和 a - 2
但在 q
中可能有 a - 1
、a - 2
、b - 1
和 b - 2
?如果发生这种情况,我应该如何设计或使用哪种技术来监控多线程的进程?
重新排序和多线程是两种不同的东西:
通过多线程,可能的输出是:
"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 状态:
The C++ compiler is permitted to perform any changes to the program as long as the following remains true:
- Accesses (reads and writes) to volatile objects occur strictly according to the semantics of the expressions in which they occur. In particular, they are not reordered with respect to other volatile accesses on the same thread.
(since C++11)
- At program termination, data written to files is exactly as if the program was executed as written.
- Prompting text which is sent to interactive devices will be shown before the program waits for input.
- If the ISO C pragma #pragma STDC FENV_ACCESS is supported and is set to ON, the changes to the floating-point environment (floating-point exceptions and rounding modes) are guaranteed to be observed by the floating-point arithmetic operators and function calls as if executed as written, except that
the result of any floating-point expression other than cast and assignment may have range and precision of a floating-point type different from the type of the expression (see FLT_EVAL_METHOD)
notwithstanding the above, intermediate results of any floating-point expression may be calculated as if to infinite range and precision (unless #pragma STDC FP_CONTRACT is OFF)
您的代码(可能 // do something
除外)不执行任何操作,因此它甚至可以完全删除 2 代码,按“c - 1”。
但是如果打印队列内容后,那么内容应该是上面显示的6个之一。
正如我们所知,编译器或 CPU 可能会根据需要重新排序执行,前提是它们遵循 as-if 规则。比如我们有这么一段代码:
C = A + B;
D = E + F;
编译器或 CPU 可能会在 C = A + B
之前执行 D = E + F
。我能理解。
下面说说另外一个案例
说我有两个线程 a
和 b
。我想在执行的时候设置一些标记,这样我就可以监控a
和b
.
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 - 1
、b - 1
、b - 2
和 a - 2
但在 q
中可能有 a - 1
、a - 2
、b - 1
和 b - 2
?如果发生这种情况,我应该如何设计或使用哪种技术来监控多线程的进程?
重新排序和多线程是两种不同的东西:
通过多线程,可能的输出是:
"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 状态:
The C++ compiler is permitted to perform any changes to the program as long as the following remains true:
- Accesses (reads and writes) to volatile objects occur strictly according to the semantics of the expressions in which they occur. In particular, they are not reordered with respect to other volatile accesses on the same thread. (since C++11)
- At program termination, data written to files is exactly as if the program was executed as written.
- Prompting text which is sent to interactive devices will be shown before the program waits for input.
- If the ISO C pragma #pragma STDC FENV_ACCESS is supported and is set to ON, the changes to the floating-point environment (floating-point exceptions and rounding modes) are guaranteed to be observed by the floating-point arithmetic operators and function calls as if executed as written, except that the result of any floating-point expression other than cast and assignment may have range and precision of a floating-point type different from the type of the expression (see FLT_EVAL_METHOD) notwithstanding the above, intermediate results of any floating-point expression may be calculated as if to infinite range and precision (unless #pragma STDC FP_CONTRACT is OFF)
您的代码(可能 // do something
除外)不执行任何操作,因此它甚至可以完全删除 2 代码,按“c - 1”。
但是如果打印队列内容后,那么内容应该是上面显示的6个之一。