在 Peterson 算法中,进程将
turn
变量切换到 other 进程。
但是,我想知道为什么我们不将turn变量切换到current进程中,如下所示:
void process0() {
flag[0] = 1; // Process 0 wants to access the critical section
turn = 0; // It's Process 0's turn to access the critical section
while (flag[1] && turn == 1); // If Process 1 wants to access the critical section and it IS Process 1's turn, then Process 0 should wait
// Process 0 accesses the critical section
flag[0] = 0; // Process 0 quits the critical section
// Remaining codes
}
void process1() {
flag[1] = 1; // Process 1 wants to access the critical section
turn = 1; // It's Process 1's turn to access the critical section
while (flag[0] && turn == 0); // If Process 0 wants to access the critical section and it IS Process 0's turn, then Process 1 should wait
// Process 1 accesses the critical section
flag[1] = 0; // Process 1 quits the critical section
// Remaining codes
}
似乎总有一个进程能够访问临界区,并且也只有一个进程可以访问临界区。那么我们为什么不将turn变量切换为当前进程号呢?
我尝试过使用这个Python代码:
import threading, random
END_POSSIBILITY = 0.001 # The possibility that one process finishes running
flag = [False, False]
turn = 0
class CriticalSection:
def __init__(self) -> None:
self.visitor = -1
def visit(self, visitor: int) -> None:
if self.visitor == -1:
self.visitor = visitor
else:
raise Exception(f"CRITICAL SECTION IS ALREADY BEING VISITED BY PROCESS {self.visitor}, CANNOT BE VISITED BY {visitor}!!!")
def unvisit(self) -> None:
self.visitor = -1
critical_section = CriticalSection()
def process0():
global turn
while True:
flag[0] = True
turn = 0
while flag[1] and turn == 1:
pass
critical_section.visit(0)
flag[0] = False
critical_section.unvisit()
if (random.random() <= END_POSSIBILITY):
break
def process1():
global turn
while True:
flag[1] = True
turn = 1
while flag[0] and turn == 0:
pass
critical_section.visit(1)
flag[1] = False
critical_section.unvisit()
if (random.random() <= END_POSSIBILITY):
break
thread0 = threading.Thread(target=process0)
thread1 = threading.Thread(target=process1)
thread0.start()
thread1.start()
我多次运行这段代码,一切正常。
假设操作顺序如下。
P1 执行时 P2 停止:
flag[0] = 1;
turn = 0;
while (flag[1] && turn == 1); // terminates immediately because turn == 0
// critical section
当 P1 处于临界区时,P2 开始执行:
flag[1] = 1;
turn = 1;
while (flag[0] && turn == 0); // terminates immediately because turn == 1
// critical section
现在两个进程同时处于临界区。
本质上,在您的版本中,任何一个进程现在都可以声明轮到自己了,而完全忽略另一个进程是否位于临界区的中间。