Transferred from: http://blog.csdn.net/tayanxunhua/article/details/38691005
The classic case of deadlock: the Philosopher's repast.
This case can lead to deadlocks .
By modifying the case in the Java Programming Ideas 4 book, the code is easier to understand and the results are relatively easy to control.
Attached code:
Chopsticks class:
1 Packagecom.tyxh.ch21.c6;2 3 Public classchopstick {4 Private BooleanTaken =false;//Judging whether this chopstick is picked up5 Public synchronized voidTake ()throwsinterruptedexception {6 while(taken) {7 //if it has been picked up, wait8 wait ();9 }Ten //if not picked up, it can be picked up and set taken to True OneTaken =true; A } - - Public synchronized voiddrop () { the //set taken to false after putting down the chopsticks and notify other chopsticks -Taken =false; - Notifyall (); - } +}
Philosopher class:
1 Packagecom.tyxh.ch21.c6;2 3 ImportJava.util.Random;4 ImportJava.util.concurrent.TimeUnit;5 6 Public classPhilosopherImplementsRunnable {7 PrivateChopstick left;//left Chopsticks8 PrivateChopstick right;//Right Chopsticks9 Ten Private Final intId//Philosopher's number One Private Final intPonderfactor;//set the think time based on this property A - PrivateRandom Rand =NewRandom (47); - Private voidPause ()throwsinterruptedexception { the if(Ponderfactor = = 0) { - return; - } -TimeUnit.MILLISECONDS.sleep (Rand.nextint (Ponderfactor *250)); + } - + PublicPhilosopher (chopstick left, chopstick right,intIdentintponder) { A This. left =Left ; at This. right =Right ; - This. ID =ident; - This. Ponderfactor =ponder; - } - - Public voidrun () { in Try{ - while(!thread.interrupted ()) { toSystem.out.println ( This+ "" + "thinking"); + pause (); - Right.take (); theSystem.out.println ( This+ "" + "take right chopsticks"); * Left.take (); $System.out.println ( This+ "" + "take Left chopsticks");Panax Notoginseng pause (); -System.out.println ( This+ "" + "eat"); the Right.drop (); +System.out.println ( This+ "+" drop right Chopsticks "); A Left.drop (); theSystem.out.println ( This+ "+" drop left chopsticks "); + } -}Catch(interruptedexception e) { $System.out.println ( This+ "Exit"); $ } - } - the PublicString toString () { - return"Phiosopher:" +ID;Wuyi } the}
Test class:
1 Packagecom.tyxh.ch21.c6;2 3 ImportJava.util.concurrent.ExecutorService;4 Importjava.util.concurrent.Executors;5 ImportJava.util.concurrent.TimeUnit;6 7 Public classDeadlockingdiningphilosophers {8 Public Static voidMain (string[] args)throwsinterruptedexception {9 intPonder = 5;Ten if(Args.length > 0) { OnePonder = Integer.parseint (args[0]); A } - intSize = 5; - if(Args.length > 1) { theSize = Integer.parseint (args[1]); - } -Executorservice exec =Executors.newcachedthreadpool (); -chopstick[] Stick =NewChopstick[size]; + - for(inti = 0; i < size; i++) { +Stick[i] =Newchopstick (); A } at - for(inti = 0; i < size; i++) { -Philosopher P =NewPhilosopher (Stick[i], stick[(i+1)%size], I, ponder); - Exec.execute (p); - } - inTimeUnit.SECONDS.sleep (3); - Exec.shutdownnow (); to + } - } the
You can adjust the ponder factor by the command-line parameters set the Philosopher's thinking time, or you can set the number of chopsticks and philosophers size.
Four necessary conditions for deadlock generation.
1> mutually exclusive use, that is, when a resource is used (occupied) by one thread, other threads cannot use the
2> can not be preempted, resource requester can not force from the resource holders to seize the resources, resources only by the resource holders to release voluntarily.
3> request and hold, that is, when the resource requester requests other resources while maintaining the old resources of the comrades.
4> cycle Wait, that is, there is a waiting queue: P1 occupies P2 resources, P2 possession of P3 resources, P3 possession of P1 resources. This creates a waiting loop.
When all four conditions are established, a deadlock is formed. Of course, in the case of a deadlock, if you break any of these conditions, you can make the deadlock disappear.
Here is only the solution for dealing with this deadlock in the book (Breaking the fourth condition):
Scenarios are:
Before the philosopher took the chopsticks in the order of the first to take the right, then take the left, but the last philosopher took the order of chopsticks to take the left, and then take the right, you can stop the loop to wait for the condition of the deadlock to prevent the deadlock occurred.
Upcoming Code:
1 for (int i = 0; i < size; i++) {2 New Philosopher (Stick[i], stick[(i+1)%size], I, ponder); 3 Exec.execute (p); 4 }
Modified to:
1 for(inti = 0; i < size; i++) {2 if(I < size-1) {3Philosopher P =NewPhilosopher (Stick[i], stick[(i+1)%size], I, ponder);4 Exec.execute (p);5}Else {6Philosopher P =NewPhilosopher (stick[0], stick[i], I, ponder);7 Exec.execute (p);8 }9}
Java concurrency, classic deadlock case-philosophers dining