choosing[i] 为真,同时 number[i] 被更新为大于 number 数组中的所有其他值——线程正在获取的新票证值。在for循环的主体中,代码首先等待choice[j]为假,这表明线程号j已经选择了它的本轮票。如果线程 j 继续执行,而线程 i 还没有进入临界区,那么 number[i] 不会改变,所以:
如果线程 j 仍在同一轮中并且尚未完成临界区,则 number[j] 是最大计算的结果,它可能会将 number[i] 的当前值带入,也可能不带入帐户,取决于线程 i 和 j 的执行的交错。
如果线程 j 在剩余部分,则 number[j] 为 0。
如果线程 j 已经开始新一轮,那么它的 number[j] 是考虑 number[i] 的当前值的最大计算的结果,因此 number[j] > number[i]。
在第一种情况下,线程 i 和 j 正在同时运行它们的 for 循环;只有其中一个将赢得 (number[j],j)
选择数组解决了 number[] 值计算中缺乏原子性的问题。如果它被删除,那么您可以让两个线程同时计算相同的值,并且每个线程都发现它在测试时具有较小的值。这可能发生在两个线程中(我使用符号 k.tmpX 来指定线程 k 的本地存储):
最初:数字[1] = 数字[2] = 0
thread 1 thread 2
//choosing[1]=true
1.tmp1 = number[1]
1.tmp2 = number[2]
//choosing[2]=true
2.tmp1 = number[1]
2.tmp2 = number[2]
number[2] = max(2.tmp1,2.tmp2)+1 = 1
//choosing[2]=false
//while (choosing[1]) {}
while (number[1]≠0 &&
(number[1],1)<(number[2],2)) {}
critical section ...
number[1] = max(1.tmp1,1.tmp2)+1 = 1
//choosing[1]=false
//while (choosing[2]) {}
while (number[2]≠0 &&
(number[2],2)<(number[1],1)) {}
critical section ...
critical section ...
两个线程计算出相同的票号。在这种情况下,面包店算法使用线程号来确定优先级。但是,线程2在线程1还在准备的时候决定进入临界线程,而线程1在决定是否进入临界区时看到了线程2的新票号,但是已经根据线程2的旧票号计算了自己的票号。所以线程 1 错误地进入了临界区。
选择数组通过阻止线程 2 进入临界区来解决这个问题。由于线程 1 在线程 2 准备进入临界区时正在计算其票号,因此线程 2 将在 while (choosing[1]) {} 上阻塞,之后它将看到 number[1] 的更新值,并且让线程 1 先进入临界区,而线程 2 等待 while (number[1]≠0 && (number[1],1)