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。但即使经过多次尝试,我也无法解决这个问题。 任何形式的帮助将不胜感激!提前谢谢。
答案 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。 我希望答案很明确。如果需要澄清,请告诉我。