哲学家就餐问题如何避免死锁 如何避免死锁

线程同步导致的问题让多线程代码安全运行的方法是让所有的方法都同步 。

  • 效率低下 。
    如果每个方法都同步,大多数线程会频繁阻塞,使程序失去了并发的意义 。-
  • 当使用多把锁时(Java中每一个对象都有自己的内置锁),线程之间可能发生死锁 。
哲学家进餐问题——死锁——示意图
哲学家就餐问题如何避免死锁 如何避免死锁

文章插图
哲学家进餐问题——死锁——代码代码很简单,Philosopher类只有三个属性,左右筷子和random:
哲学家就餐问题如何避免死锁 如何避免死锁

文章插图
Philosopher类
下面是具体的逻辑代码:
哲学家就餐问题如何避免死锁 如何避免死锁

文章插图
测试该代码:
哲学家就餐问题如何避免死锁 如何避免死锁

文章插图
哲学家进餐问题——死锁——代码运行多久会死锁测试过五个哲学家实例,最长时间可以运行一周,直到某个时刻突然都停了下来 。
哲学家进餐问题——死锁——原因如果所有哲学家同时决定进餐,都拿起左手边的筷子,那么就无法进行下去——所有人都持有一只筷子并等待右手边的人放下筷子 。这时死锁就出现了 。
哲学家进餐问题——死锁条件一个线程需要多把锁时,就需要考虑死锁的可能性 。
哲学家进餐问题——如何避免死锁总是按照一个全局的固定的顺序获取多把锁 。
哲学家就餐问题如何避免死锁 如何避免死锁

文章插图
不是按左右手的顺序拿筷子,而是按照筷子编号获取锁(不关心编号的具体规则,只要保证编号是全局唯一且有序的) 。
如果获取锁的代码写得比较集中,就有利于维护这个全局顺序 。而对于规模较大的程序,使用锁的地方比较零散,各处都遵守这个顺序就变得不太实际 。
用对象的散列值作为锁的全局顺序
哲学家就餐问题如何避免死锁 如何避免死锁

文章插图
适用于所有Java对象,不用为锁对象专门定义并维护一个顺序 。
【哲学家就餐问题如何避免死锁 如何避免死锁】但对象的散列值并不能保证唯一性(对象的散列值可能重复) 。如果不是迫不得已,不要使用这个技巧 。

    推荐阅读