1. The problem of philosophers eating noodles: that is to say, there are five philosophers in a circle, and then there are five chopsticks on the table, each of them has a chopstick beside them. This leads to a deadlock problem. Everyone has the resources needed by others, but at the same time waits for the resources owned by others, and everyone will not give up the resources they have before they get all the resources.
2. Common deadlock problems:
1) Cross lock causes program deadlock. Take an example
public class TestDemo2 { //Program deadlock caused by cross lock private final Object R1 = new Object(); private final Object R2 = new Object(); public void func1(){ synchronized (R1){ synchronized (R2){ //dosomething } } } public void func2(){ synchronized (R2){ synchronized (R1){ //dosomething } } } public static void main(String[] args) { } }
In this example, we can see that A has the lock of R1 at this time, and then it is waiting for the lock of R2, but thread B has the lock of R2 at this time, and it is waiting for the lock of R1. At this time, thread A and thread B both hold the lock required by each other, but no one will release the lock they hold now, and enter the infinite waiting, which forms the deadlock problem.
2) Out of memory
If there are two threads, thread a obtains 10MB memory, thread DB obtains 20MB memory, both threads need 30MB to execute, but at this time, only 20MB is left in the available memory of the system, which will cause the situation of insufficient memory.
3) One question one answer data exchange
For example, the server opens the port for the client and waits for the client to access; the client sends the access request and waits for receiving; but at this time, the server misses the client's request, which may cause deadlock.
4) Deadlock caused by dead cycle
(note that this code should not be run, otherwise it may cause running problems.)
HashMap<String, String> map = new HashMap<>();
for(int i=0; i<2; i++){
new Thread(){
public void run(){
for(i = 1; i<Integer.MAX_VALUE; i++){
map.put(String.valueOf(i), String.valueOf(i));
}
}
}.start();
}
3. Necessary conditions for deadlock
1) Mutually exclusive condition: each resource can only be occupied by one thread in a certain period of time
2) Non preemptive condition: before the resource obtained by a thread is used up, other threads cannot forcibly seize it
3) Possession and application condition: the thread has already occupied at least one resource and applied for a new resource. The resource is occupied by another thread, and the thread is blocked
4) Circular waiting condition: one thread waits for other threads to release resources, and other threads wait for another thread to release resources. Finally, one thread waits for the first thread to release resources, which makes everyone locked
Then how to avoid deadlock: we can only say that the code logic does not meet the above four items at the same time.
4. Code of philosopher's noodles:
class ChopSticks{ protected String name; public ChopSticks(String name){ this.name = name; } } class PhilosopherThread extends Thread{ private ChopSticks lefeChop; private ChopSticks rightChop; private String name; public PhilosopherThread(String name, ChopSticks lefeChop, ChopSticks rightChop){ this.name = name; this.lefeChop = lefeChop; this.rightChop = rightChop; } @Override public void run() { //Simulated eating noodles synchronized (lefeChop){ System.out.println(name + " got the chopstick "+lefeChop.name); synchronized (rightChop){ System.out.println(name + " got the chopstick "+rightChop.name); System.out.println(name + "is eating noodles"); try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(name + " release the chopstick "+lefeChop.name+" and "+rightChop.name); } } } public class TestDemo{ public static void main(String[] args) { ChopSticks chopStick0 = new ChopSticks("0"); ChopSticks chopStick1 = new ChopSticks("1"); ChopSticks chopStick2 = new ChopSticks("2"); ChopSticks chopStick3 = new ChopSticks("3"); ChopSticks chopStick4 = new ChopSticks("4"); new PhilosopherThread("thread0", chopStick0, chopStick1).start(); new PhilosopherThread("thread1", chopStick1, chopStick2).start(); new PhilosopherThread("thread2", chopStick2, chopStick3).start(); new PhilosopherThread("thread3", chopStick3, chopStick4).start(); new PhilosopherThread("thread4", chopStick4, chopStick0).start(); } }
At this time, it will cause deadlock. Then we need to use wait(),notify(),notifyAll() mechanism to solve this problem. Before philosophers eat, they must ensure that chopsticks on both sides can be used before eating. The code is as follows:
class Chopsticks{ protected static HashMap<Integer, Boolean> map = new HashMap<>(); static{ map.put(0, false); map.put(1, false); map.put(2, false); map.put(3, false); map.put(4, false); } public synchronized void getChopStick(){ //First, get the same chopstick - "curNo" as the current thread name String curName = Thread.currentThread().getName(); int curNo = Integer.parseInt(curName); //The other side is nextNo = (curNo+1)%5 int nextNo = (curNo+1)%5; //As long as map.get(curNo)==true or map.get(nextNo)==true while(map.get(curNo) || map.get(nextNo)){ //The current thread is blocked and the right to use a chopstick is released try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //Use chopsticks to eat noodles after being awakened map.put(curNo, true); map.put(nextNo, true); System.out.println("Thread "+curName+" got the chopstick "+curNo+" and "+nextNo ); } public synchronized void freeChopStick(){ String curName = Thread.currentThread().getName(); int curNo = Integer.parseInt(curName); int nextNo = (curNo+1)%5; map.put(curNo, false); map.put(nextNo, false); this.notifyAll(); } } public class TestDemo{ public static void main(String[] args) { Chopsticks chopSticks = new Chopsticks(); for(int i=0; i<5; i++){ new Thread(String.valueOf(i)){ @Override public void run() { while(true){ chopSticks.getChopStick(); try { System.out.println("Thread "+Thread.currentThread().getName()+" is eating noodles"); TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } chopSticks.freeChopStick(); } } }.start(); } } }
At this time, it was found that the deadlock of philosophers' eating noodles had been solved.