1971年,著名的计算机科学家艾兹格·迪科斯彻提出了一个同步问题,即假设有五台计算机同时去访问五份共享的内存数据,系统应该如何处理?后来为了方便表述和理解,演变成了计算机科学中大名鼎鼎的“哲学家就餐”问题,用来诠释系统死锁和资源耗尽的情况。

在具体介绍哲学家就餐问题前,我们需要明白一些名词的含义:
在理解了上述概念后,我们来具体看一下哲学家就餐问题到底说了个什么?
哲学家有五个哲学家围绕着一张圆桌,分别坐在五张椅子上。在圆桌上有五个碗和五支筷子,一个哲学家进行思考,吃东西的时候时便取用他左、右最靠近的筷子,只有在他拿到两支筷子时才能进餐。进餐完毕,放下筷子又继续思考。

哲学家们遵循着一定的规则:
由于哲学家之间不会进行交流(线程彼此之间独立),就可能会导致某些哲学家们一直处于等待筷子的状态,也就是我们上文说到的死锁情况。又或者说,每个哲学家都有左边的筷子,一直都在等右边的筷子(相反亦可)。如果这样的话,即使不出现死锁,也会发生筷子不够用的情况(资源耗尽)。
无论哪一种情况都是设计者们不想遇到的,针对这些问题,也有相应的解决方案,目前最常用的主要有以下三种。

一个服务员受不了这帮哲学家们磨磨蹭蹭的,说:“都别等着了,我给你们分筷子!”由于服务员知道哪位哲学家正在使用筷子,所以可以避免出现死锁这样的问题发生。
服务员给哲学家依次从A到E编号。假设此时A和C在吃东西,则有四只筷子在使用中。B坐在A和C之间,所有筷子都不能使用,而D和E之间有一只空余的筷子。假设这时D想要吃东西。如果他拿起了第五只筷子,就有可能发生死锁。这个时候服务员会让他先等着。这样就可以保证,当两根筷子空余出来时,一定有一位哲学家可以成功的得到一对筷子,从而避免了死锁。

资源分级解法和服务员机制有些类似,会为资源分配一个偏序或者分级的关系,并约定所有资源都按照这种顺序获取,按相反顺序释放,保证不会有两个无关资源同时被同一项工作所需要。
在哲学家就餐问题中,给筷子按照一定的规则编号,每一个哲学家总是先拿起左右两边编号较低的筷子,再拿编号较高的。用完筷子后,他总是先放下编号较高的筷子,再放下编号较低的。在这种情况下,当四位哲学家同时拿起他们手边编号较低的筷子时,只有编号最高的筷子留在桌上,从而第五位哲学家就不能使用任何一只筷子了。而且,只有一位哲学家能使用最高编号的筷子,所以他能使用两只筷子用餐。当他吃完后,他会先放下编号最高的筷子,再放下编号较低的筷子,从而让另一位哲学家拿起后边的这只开始吃东西。
这种方法也是目前最为实用的一种解法。

这种方法是K. Mani Chandy和J. Misra在1984年提出的一个解法,允许任意的用户争用任意数量的资源。和其他解法不同的是,这里使用到的编号都是任意的,也是因为这个原因,该解法允许很大的并行性。
对每一对竞争一个资源的哲学家,新拿一个筷子,给编号较低的哲学家。每只筷子都是“干净的”或者“脏的”。最初,所有的筷子都是脏的。当一位哲学家要吃东西时,他必须从与他竞争的邻居那里得到。对每只他当前没有的筷子,他都发送一个请求。当拥有筷子的哲学家收到请求时,如果筷子是干净的,那么他继续留着,否则就擦干净并交出筷子。当某个哲学家吃东西后,他的筷子就变脏了。如果另一个哲学家之前请求过其中的筷子,那他就擦干净并交出筷子。
哲学家就餐问题实质上多线程使用中会出现的问题,其实在计算机中,多进程和多线程的并行互斥在实际运用中还有很多需要注意的地方,这些知识较为抽象,在学习的时候一定要搞清楚每个名词的含义,最好可以找代码动手敲一敲,看看运行的结果,学习编程最好的方式就是动手去做。
| 留言与评论(共有 0 条评论) |