在竞争条件下循环

时间:2014-10-06 09:10:31

标签: loops concurrency process race-condition

2个进程P0和P1与竞争条件同时运行。 我想计算x在执行期间可能采用的最大值和最小值。 x的初始值为0

P0:
for( int i=0; i<1000; i++){
   x++;
   x-- ;
   x++;
}

P1:
for( int j=0; j<2000; j++){
   x-- ;
   x++;
}

最大值应为4000,最小值应为-2999。但即使经过多次尝试,我也无法解决这个问题。 任何形式的帮助将不胜感激!提前谢谢。

2 个答案:

答案 0 :(得分:2)

code247,

理解这个问题的关键在于查看每次递增和递减时生成的汇编代码。

每个后增量将生成以下代码:

 ld [%fp-4], %l0
 add %l0, 1, %l0
 st %l0, [%fp-4]

每次减少后都会产生以下代码:

 ld [%fp-4], %l0
 sub %l0, 1, %l0
 st %l0, [%fp-4]

现在您正在学习并发性的是,如果您选择不使用mutex locks和其他concurrency control techniques,上述汇编指令实际上可以以非确定性方式执行。

现在,我们将获得最大值4000的值。

这是代码的执行方式:

P0:
for( int i=0; i<1000; i++){
   x++;   //lets call this step 1
   x-- ;  //step 2
   x++;   //step 3
}

P1:
for( int j=0; j<2000; j++){
   x-- ;  //step a (using letters to denote difference in processes)
   x++;   //step b
 }

您的代码将按以下方式执行以实现最大值:

step 1
step a
step b
step 2
step 3

现在关键在于识别你的reads and writes are going to be dirty。这意味着在上面的汇编代码中,加载的值并不总是反映正确的值。以下是这将如何发挥作用:

 ld [%fp-4], %l0  //read current value of 'x' for step 1
 add %l0, 1, %l0  //performs increments
 st %l0, [%fp-4]  //stores value from step 1 
 ld [%fp-4], %l0  //begins read for step a
 sub %l0, 1, %l0  //performs decrement
 ld [%fp-4], %l0  //performs a DIRTY-READ for step b (notice step a hasn't finished executing)
 add %l0, 1, %l0  //performs increment
 st %l0, [%fp-4]  //stores value from increment (value from decrement is now outdated and lost) (this is a dirty write)
 st %l0, [%fp-4]  //stores value from decrement (this value is actually lost)(this is a dirty write)

从上面的执行中,您可以看到程序集将交织在一起,并且您不会在没有proper use of concurrency的情况下将正确的'x'值保存到堆栈中。这就是你将如何获得4000,因为在你的程序集的一些排列中,你将一致地处理4个增量运算符,而你的减量运算符的结果将不会被正确保存。以同样的方式,你将获得-2999值,通过串行执行减量运算符,而不是在增量运算符之后正确保持x的值。

如果您有任何疑问,请与我们联系!

答案 1 :(得分:1)

我认为最小值应该是-2999本身。我将尝试展示如何。

我假设步骤按顺序1,2,3,a,b(Devarsh先生在其中一个答案中给出的名称)运行。 现在注意到每个循环结束时必须有一个递增操作。对于除最后一次迭代之外的所有迭代,步骤2或步骤a可以分别读取并破坏由(步骤b +步骤1)或步骤b完成的增量。但是在最后一次迭代中,递减操作不能破坏接下来会发生的增量值。因此答案为-2999而不是-3000。 我希望答案很明确。如果需要澄清,请告诉我。