产生死锁的条件:
1.有至少一个资源不能共享
2.至少有一个任务必须持有一个资源并且等待获取另一个被别的任务持有的资源
3.资源不能任务抢占
4.必须有循环等待
只要打破其中一个条件就不会产生死锁,通常是打破第4个条件
package DeadLock; public class Chopstick { private boolean taken = false; public synchronized void take() throws InterruptedException { while (taken) { wait(); } taken = true; } public synchronized void drop() { taken = false; notifyAll(); } }
package DeadLock; import java.util.Random; import java.util.concurrent.TimeUnit; public class Philosopher implements Runnable { private Chopstick left; private Chopstick right; private final int id; private final int ponderFactor; private Random rand = new Random(47); private void pause() throws InterruptedException { if (ponderFactor == 0) return; //赞同随机毫秒数 TimeUnit.MILLISECONDS.sleep(rand.nextInt(ponderFactor * 250)); } public Philosopher(Chopstick left, Chopstick right, int ident, int ponder) { this.left = left; this.right = right; id = ident; ponderFactor = ponder; } @Override public void run() { try { while (!Thread.interrupted()) { System.out.println(this + " " + "thinking"); pause(); // Philosopher becomes hungry System.out.println(this + " " + " grabbing right"); right.take(); System.out.println(this + " " + "grabbing left"); left.take(); System.out.println(this + " " + "eating"); pause(); right.drop(); left.drop(); } } catch (InterruptedException e) { System.out.println(this + " " + "exiting via interrupt"); } } public String toString() { return "Philosopher " + id; } }
造成死锁
package DeadLock; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class DeadlockingDiningPhilosophers { public static void main(String[] args) throws Exception { int ponder = 5; if (args.length > 0) ponder = Integer.parseInt(args[0]); int size = 5; if (args.length > 1) size = Integer.parseInt(args[1]); ExecutorService exec = Executors.newCachedThreadPool(); Chopstick[] sticks = new Chopstick[size]; for (int i = 0; i < size; i++) { exec.execute(new Philosopher(sticks[i], sticks[(i + 1) % size], i, ponder)); } if (args.length == 3 && args[2].equals("timeout")) TimeUnit.SECONDS.sleep(5); else { System.out.println("Press'Enter' to quit"); System.in.read(); } exec.shutdownNow(); } }
避免死锁
package DeadLock; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import javax.print.attribute.Size2DSyntax; public class FixedDiningPhilosophers { public static void main(String[] args) throws Exception{ int ponder=5; if(args.length>0) ponder=Integer.parseInt(args[0]); int size=5; if(args.length>1) size=Integer.parseInt(args[1]); ExecutorService exec=Executors.newCachedThreadPool(); Chopstick[] sticks=new Chopstick[size]; for (int i = 0; i < size; i++) { sticks[i]=new Chopstick(); } for (int i = 0; i < size; i++) { if(i<(size-1)) exec.execute(new Philosopher(sticks[i],sticks[i+1], i, ponder)); else exec.execute(new Philosopher(sticks[0], sticks[i], i, ponder)); } if(args.length==3&&args[2].equals("timeout")) TimeUnit.SECONDS.sleep(5); else{ System.out.println("Press 'Enter' to quit"); System.in.read(); } exec.shutdownNow(); } }