我的解决方案是否满足互斥要求?

Does my solution satisfy mutual exclusion requirements?

在网上找到了解决互斥问题的方法,有两个进程P0和P1。 (假设变量turn初始化为0)

volatile int turn;  

进程 P0:

/* Other code */
  while (turn != 0) { } /* Do nothing and wait. */
  Critical Section /* . . . */
  turn = 1;
  /* Other code */

进程 P1:

/*Other code*/
  while (turn != 1) { } /* Do nothing and wait. */
  Critical Section /* . . . */
  turn = 0;
  /* Other code */

这个方案是如何解决互斥问题的?完全看不懂。

假设没有其他代码可以将 turn 设置为 0 或 1 以外的值,并且假设唯一干扰 turn 变量的是 P0 和 P1,那么这确实解决了互斥属性。具体来说,您说 turn 初始化为 0。这意味着 P1 无法进入临界区:它在 while (turn != 1) 循环中很忙,并且会一直停留在该循环中,直到设置 turn == 1。鉴于我们假设只有 P0 和 P1 对 turn 进行更改,这意味着 P1 无法进入临界区,直到 P0 将 turn 设置为 1。因此 P0 将立即退出它的 while (turn != 0) 循环(因为 turn 最初是 0) 并安全地进入它的临界区。它知道 P1 不能进入它的临界区,直到 turn 被设置为 1 并且只有在 P0 离开它的临界区之后才会发生。一旦 P0 将 turn 设置为 1,P0 将卡在它的 while (turn != 0) 循环中,直到 P1 将其释放,所以现在 P1 在它的临界区而 P0 不能在它的临界区。等等。

一个简单的想法就是两个人和一根警棍。他们每个人都同意不做任何事情(进入他们的关键部分),除非他们拿着接力棒。所以第 1 个人一开始拿着接力棒,可以自由地做一些事情,因为他们知道第 2 个人什么也做不了——他们没有接力棒。一旦第 1 个人完成,他们将接力棒交给第 2 个人。第 2 个人现在可以自由地做他们想做的任何事情,他们知道第 1 个人什么都不做,只是在等待接力棒交还给他们。

正如@JustinSteele 所指出的,这绝对不能解决互斥问题。也许如果您将转数更改为布尔值,您可能会得到一个肮脏的修复,因为布尔值仅包含两个值。如果你想要一种更合适的方式来提供互斥,我建议你看看互斥量、信号量和条件变量。祝你好运!

如果 P0 和 P1 都被执行,并且每个只执行一次,那么 P0 确实会先于 P1 进入临界区。

根据Java 内存模型,此程序已正确同步,因为所有线程间操作都是易失性读取和写入。因此程序顺序一致,便于分析。

或者更具体地说,所有volatile的读写都是一个总序(与编程顺序一致);此顺序将保证关键部分的互斥性。


但是,这里有一个严重的问题。如果 P1 先到达,它必须等待 P0,无论 P0 到达多晚。这是很不公平的。并且,如果不执行P0,则P1不能前进。并且,如果 P0 被执行而 P1 没有被执行,P0 就不能再次进入临界区(它必须等待 P1 重新开始)。这种锁定机制只允许严格的 P0-P1-P0-P1-... 序列(除非这正是所需要的)

解决这个问题,有Dekker算法,Peterson算法等,看这个post - https://cs.stackexchange.com/a/12632