assembly - 这两个并行执行的函数怎么可能输出不太可能的结果呢?

标签 assembly concurrency cpu-architecture

我有这两个函数,并行执行:

int x = 10 // a common variable

void P1(){                   void P2(){
   while(1){                    while(1){
   x--;                         x--;
   x++;                         x++;
   if(x!=10)                    if(x!=10)
      printf("x=%d",x);             printf("x=%d",x);
   }                            }
}                             }

parbegin P1(); P2();
parend

函数偶尔会输出 x=8,这看起来不可能。

是否与 x--x++ 操作实际上被翻译的事实有关机器代码中的 3 条指令(参见符号汇编解码)?

LD    R0, X             // LOAD into R0 the value of x
INCR  R0 (or DECR R0)   // { INCR | DECR }-increase/decrease the value of R0 by 1
STO   R0, X             // STORE the new value back to x

如果是,
那么指令的顺序是什么,以便生成输出 "x=8"

如果没有,
那为什么它偶尔会打印x=8

最佳答案

完全有可能,而且正是由于你怀疑的原因,而不是完全按照你怀疑的顺序。

x--语句不是原子的,它由加载操作、减量操作和存储操作组成。因此,如果 x-- 被另一个线程抢占,结果可能就像 x-- 语句根本没有执行一样。但这不会产生 8,它实际上会导致 x 达不到 8 这样低的值。

但是,同样适用于 x++ 语句:抢占可能导致 x++ 永远不会发生,所以在这种情况下的结果将是 x 将无法超过 9,因此只需一次成功的 x-- 即可将其降至 8 .

所以,如果取消的x++多于x--,那么x完全有可能变成8。实际上,在您的代码示例中,x 完全有可能收到您能想到的任何值。

关于assembly - 这两个并行执行的函数怎么可能输出不太可能的结果呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60355962/

相关文章:

assembly - 有什么区别——MOV指令

mysql - 在 mysql 中插入行时锁定

协程 : Where to close

c# - 为什么 C# System.Decimal (decimal) "waste"位?

linux - 在 QEMU 中记录动态指令轨迹或直方图?

c - 来自 GCC 编译器的 `__asm nop` 在 Windows 中相当于 `asm volatile("nop");`

multithreading - 并发 Haskell 是否仍仅限于单个操作系统线程?

assembly - 我可以在现代系统上的汇编中使用 movl 代替 movb 或 movw 吗?

linux - 如何使用 Intel Pin 工具生成分支列表?

assembly - 使用基本内核实现 GDT