Philosopher problem solving

recurrent

chopsticks

public class Chopsticks {
    
    

}

philosopher

public class Philosopher  {
    
    

    public Philosopher(String name, Chopsticks left, Chopsticks right) {
    
    
        this.name = name;
        this.left = left;
        this.right = right;
    }

    private String name;
	// 左手筷子	
    private Chopsticks left;
	// 右手筷子
    private Chopsticks right;

    public void eating(){
    
    
        synchronized (left) {
    
    
            try {
    
    
                Thread.sleep(1000);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            synchronized (right) {
    
    
                try {
    
    
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
                System.out.println(this.name+" is eating ...");
            }
        }
    }
}

Main function

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Chopsticks c1 = new Chopsticks();
        Chopsticks c2 = new Chopsticks();
        Chopsticks c3 = new Chopsticks();
        Chopsticks c4 = new Chopsticks();
        Chopsticks c5 = new Chopsticks();

        // 分配筷子
        Philosopher p1 = new Philosopher("p1",c1,c2);
        Philosopher p2 = new Philosopher("p2",c2,c3);
        Philosopher p3 = new Philosopher("p3",c3,c4);
        Philosopher p4 = new Philosopher("p4",c4,c5);
        Philosopher p5 = new Philosopher("p5",c5,c1);

        new Thread(()->{
    
    
            p1.eating();
        }).start();
        new Thread(()->{
    
    
            p2.eating();
        }).start();
        new Thread(()->{
    
    
            p3.eating();
        }).start();
        new Thread(()->{
    
    
            p4.eating();
        }).start();
        new Thread(()->{
    
    
            p5.eating();
        }).start();

    }
}

When in use, the left hand is allocated first, and then the right hand is allocated, resulting in a deadlock problem.

View with jps

  1. Get the process number first
    Insert picture description here

  2. View the deadlock installation status according to the process number
    Insert picture description here

  3. Deadlock details
    Insert picture description here

solve

Above, the philosopher p1 first obtains the left-hand chopsticks c1, and the philosopher p5 first obtains the left-hand chopsticks c5; then the philosopher p1 then obtains the right-hand chopsticks c5, but at this time c5 is occupied by the philosopher p5 and cannot be robbed, so p1 waiting. Other philosophers are similar, which caused a deadlock.

Allocate resources by priority

In the above example, when assigning, first distribute by the left hand, and then distribute by the right hand. We can change the allocation method and allocate resources in order. In the above example, only p5 resources are not allocated in order, we can make the following modifications.

Insert picture description here
The result of the operation is shown in the figure below, and p5 is executed last. The deadlock problem can be solved simply by using the sequential allocation of resources , but since p5 is always the last to obtain resources, it will cause starvation problems.
Insert picture description here

Waiting for release

In the above example, the occurrence of deadlock loop waiting conditions is avoided by sequential allocation. In this example, inalienable conditions can be avoided and deadlocks can be avoided. When the philosopher obtains the resources of the left hand, if he fails to apply for the resources of the right hand in time, he will release all the resources he occupied.

chopsticks

Modify the code of chopsticks to inherit reentrantlock so that it can be locked and released.

public class Chopsticks  extends ReentrantLock {
    
    

}

philosopher

Modify the code of the eating method, and the others remain unchanged. If the philosopher fails to obtain the left hand, it continues to wait. If the philosopher obtains the chopsticks of the left hand but not the chopsticks of the right hand, he releases the chopsticks of the left hand.

public void eating(){
    
    
       while(true) {
    
    
           try {
    
    
               Thread.sleep(1000);
           } catch (InterruptedException e) {
    
    
               e.printStackTrace();
           }
           if (left.tryLock()) {
    
    
               try {
    
    
                   try {
    
    
                       Thread.sleep(1000);
                   } catch (InterruptedException e) {
    
    
                       e.printStackTrace();
                   }
                   if(right.tryLock()) {
    
    
                       try{
    
    
                           System.out.println(this.name+" is eating ...");
                           break;
                       }finally {
    
    
                           right.unlock();
                       }
                   }
               } finally {
    
    
                   left.unlock();
               }
           }
       }
   }

The results of the operation are as follows. p5 is not always at the end, so there is no hunger problem.
Insert picture description here

Guess you like

Origin blog.csdn.net/qq_41948178/article/details/107813434