描述
哲学家聚餐问题是并发编程中的经典计算机科学问题。哲学家聚餐问题将导致循环死锁问题。循环死锁是死锁问题的一种变体。发生死锁之后,恢复的唯一方法是重新启动 JVM。
请参考上图。您可以看到:
- “Thread-0”持有锁 L1 并在等待锁 L2。
- “Thread-1”持有锁 L2 并在等待锁 L3。
- “Thread-2”持有锁 L3 并在等待锁 L4。
- “Thread-3”持有锁 L4 并在等待锁 L1。
由于每个线程都持有一个锁,其他线程正好也在等待这个锁,这最终就导致了循环死锁。此时就需要对代码进行重新设计以打破这种循环死锁模式。
示例
下方是一个取自哲学家聚餐问题程序 JVM 实例的线程转储文件,其中显示了循环死锁问题的一些信息。
"Thread-4" prio=6 tid=0x0000000007466800 nid=0x158f5c waiting on condition [0x0000000008fcf000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for 0x00000007ac3b2718 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
at java.util.concurrent.locks.LockSupport.park(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(Unknown Source)
at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(Unknown Source)
at java.util.concurrent.locks.ReentrantLock.lock(Unknown Source)
at com.tier1app.dinning.Philosopher.pickUpRightChopstick(DiningPhilosophers.java:110)
at com.tier1app.dinning.Philosopher.run(DiningPhilosophers.java:78)
at java.lang.Thread.run(Unknown Source)
Locked ownable synchronizers:
- 0x00000007ac3b27d8 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
"Thread-3" prio=6 tid=0x0000000007465800 nid=0x158f58 waiting on condition [0x0000000008e0f000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for 0x00000007ac3b27d8 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
at java.util.concurrent.locks.LockSupport.park(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(Unknown Source)
at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(Unknown Source)
at java.util.concurrent.locks.ReentrantLock.lock(Unknown Source)
at com.tier1app.dinning.Philosopher.pickUpRightChopstick(DiningPhilosophers.java:110)
at com.tier1app.dinning.Philosopher.run(DiningPhilosophers.java:78)
at java.lang.Thread.run(Unknown Source)
Locked ownable synchronizers:
- 0x00000007ac3b27a8 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
"Thread-2" prio=6 tid=0x0000000007465000 nid=0x158f54 waiting on condition [0x000000000895e000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for 0x00000007ac3b27a8 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
at java.util.concurrent.locks.LockSupport.park(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(Unknown Source)
at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(Unknown Source)
at java.util.concurrent.locks.ReentrantLock.lock(Unknown Source)
at com.tier1app.dinning.Philosopher.pickUpRightChopstick(DiningPhilosophers.java:110)
at com.tier1app.dinning.Philosopher.run(DiningPhilosophers.java:78)
at java.lang.Thread.run(Unknown Source)
Locked ownable synchronizers:
- 0x00000007ac3b2778 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
"Thread-1" prio=6 tid=0x0000000007462000 nid=0x158f50 waiting on condition [0x0000000008cce000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for 0x00000007ac3b2778 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
at java.util.concurrent.locks.LockSupport.park(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(Unknown Source)
at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(Unknown Source)
at java.util.concurrent.locks.ReentrantLock.lock(Unknown Source)
at com.tier1app.dinning.Philosopher.pickUpRightChopstick(DiningPhilosophers.java:110)
at com.tier1app.dinning.Philosopher.run(DiningPhilosophers.java:78)
at java.lang.Thread.run(Unknown Source)
Locked ownable synchronizers:
- 0x00000007ac3b2748 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
"Thread-0" prio=6 tid=0x0000000007461800 nid=0x158f4c waiting on condition [0x0000000008ace000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for 0x00000007ac3b2748 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
at java.util.concurrent.locks.LockSupport.park(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(Unknown Source)
at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(Unknown Source)
at java.util.concurrent.locks.ReentrantLock.lock(Unknown Source)
at com.tier1app.dinning.Philosopher.pickUpRightChopstick(DiningPhilosophers.java:110)
at com.tier1app.dinning.Philosopher.run(DiningPhilosophers.java:78)
at java.lang.Thread.run(Unknown Source)
Locked ownable synchronizers:
- 0x00000007ac3b2718 (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
从以上转储文件中,我们可以看到
- “Thread-4”正在等待由“Thread-0”持有的 0x00000007ac3b2718
- “Thread-0”正在等待由“Thread-1”持有的 0x00000007ac3b2748
- “Thread-1”正在等待由“Thread-2”持有的 0x00000007ac3b2778
- “Thread-2”正在等待由“Thread-3”持有的 0x00000007ac3b27a8
- “Thread-3”正在等待由“Thread-4”持有的 0x00000007ac3b27d8
Leave a Reply