并发代码中的程序顺序

时间:2019-01-12 02:37:13

标签: concurrency parallel-processing

给出以下代码:

int x = 0; co x:= x + 1 || x := x - 1 oc

显然,可能的值为x = {0, -1, 1}

我试图了解这是如何发生的,并且我读到有关原子弹的事,只有它们发生时,它们才会发生。 在本书中,给出了一个示例,我们可以将语句x := x + 1分解为原子语句,例如。

READ X (R1) INC WRITE(W1)

x := x - 1 进入:

READ X (R2) DEC WRITE(W2)

它说INC WRITEREAD inc的行为都好像是原子的,我真的不明白为什么做这个假设是安全的吗?

然后,看来该程序顺序返回值-1R1 -> R2 -> W1 -> W2,我不明白为什么?

据我所知,似乎我们正在读取x的值,然后再次读取它,然后再使其减一,然后再去减一,这不应该等于0

感谢帮助。

1 个答案:

答案 0 :(得分:0)

并发问题是您无法控制并发访问的顺序。因此,我们做出以下假设:
-x是由不同线程访问的全局变量
-x ++和x--由独立线程执行。

如您的书所述,对共享变量执行读-修改-写是一个三步过程:
1 /将var读入处理器reg
2 /修改处理器规则
3 /将处理器寄存器写入寄存器
这些单独的动作中的每一个对应于处理器指令,因此是 atomic 。但是全局读-修改-写操作不是,可以被其他并发操作拆分。

现在考虑并发操作

 Thread A                          Thread B
 1/ read x->regA                   a/ read x->regB
 2/ regA++                         b/ regB-- 
 3/ write regA->x                  c/ write regB

在一个线程内,将遵循操作顺序123或abc,但是在线程A和B之间,任何相对顺序都是可能的。

有了123abc,我们得到了预期的结果。 x由线程A更改为1,然后由线程B读取,递减,最后x = 0
abc123相同

但是其他排序将导致不同的结果。 例如:1a2b3c

 Thread A                          Thread B
 1/ read x->regA=0                   
                                   a/ read x->regB=0
 2/ regA++=1                       
                                   b/ regB--=-1 
 3/ write regA->x=1
                                   c/ write regB->x=-1

最后是x = -1。

但是如果订购1abc23,我们将得到x = 1。

 Thread A                          Thread B
 1/ read x->regA=0                   
                                   a/ read x->regB=0
                                   b/ regB--=-1 
                                   c/ write regB->x=-1
 2/ regA++=1    
 3/ write regA->x=1                   

所有订单均可以到达,结果将为\ in {-1,0,1}

获得确定性结果的唯一方法是使用原子读取-修改-写入指令。所有现代处理器都具有执行此操作的手段(获取和添加或加载链接/存储条件),在这种情况下,无法拆分序列123或abc。唯一可能的排序将是123abc或abc123,并且两者都会进行x = 0的确定性结果。