五个哲学家就餐问题

五个哲学家问题是操作系统信号量的一个典型例子。

有五个哲学家围坐在一圆桌旁,桌中央有一盘通心面,每个人面前有一只空盘子,每两人之间放一把叉子。每个哲学家思考、饥饿、然后吃通心面。为了吃面,每个哲学家必须获得两把叉子,且每人只能直接从自己左边或右边去取叉子。

可见,对于同一把叉子来说,两个哲学家对此叉子的使用构成了互斥关系。容易得到,任意两个相邻哲学家无法同时就餐,五个人中最多只有两个哲学家能同时用餐。

img-2024-04-07 19-47-39.png

信号量法

为了便于讨论,逆时针给所有哲学家及对应右手边的叉子进行编号,得到算法

semaphore fork[5]
for (int i=0;i<5;++)
	fork[i]=1;
cobegin
	process philosopher_i() {
		while (true);
			P(fork[i]);
			P(fork[(i+1)%5]);
			eat();
			V(fork[i]);
			V(fork[(i+1)%5]);
		}
	}
coend

但是上述解法可能出现永远等待,比如所有哲学家都拿起了左手的叉子,再等待右手的叉子。可是所有人都不愿意放下左手的叉子,导致出现死锁问题。有若干种办法可避免死锁:

  • 至多允许四个哲学家同时吃;
  • 奇数号先取左手边的叉子,偶数号先取右手边的叉子;
  • 每个哲学家取到手边的两把叉子才吃,否则一把叉子也不取。
  • 设置超时