Deadlock and multithreaded communication problems

deadlock

Deadlock usually occurs when threads on either side need to run opposite to each other to continue running.

Example

public static void main(String[] args) {
       Criminal c = new Criminal();
       Police p = new Police();
        Mythread thread = new Mythread(c,p);
        thread.start();// Police shout
        c.say(p);// Criminals shout

    }
    static  class  Mythread extends  Thread{
        private  Criminal c;
        private  Police p;
        public  Mythread(Criminal c,Police p){// Make sure you are the same person as the police criminals in the main method
            this.c =c;
            this.p = p;
        }
        @Override
        public void run() {
            p.say(c); //  Police shout
        }

    }

    static  class  Criminal{// Criminals
        public synchronized void say(Police p){// The criminal shouted to the police
            System.out.println("If you let me go, I'll take the hostage");
            p.fun();					//  Get a response from the police to release the criminal
        }
        public synchronized void fun(){// Response from the criminal
            System.out.println("Hostage Release,Criminals Escape");
        }
    }
    static  class Police{
        public synchronized void  say(Criminal c){// The police shouted at the prisoner
            System.out.println("If you take a hostage, I'll let you go");
            c.fun();					// Get a response to the prisoner's release of the hostage
        }
        public synchronized void fun(){// Police response
            System.out.println("Rescue succeeded,Criminals Escape");
        }
    }
}

One of the possible outcomes (deadlock)

If you let me go, I'll take the hostage
 If you take a hostage, I'll let you go

Analysis

  • In this program, there are two threads, one is the prisoner's shout in the main thread, the other is the police's shout in Mythread s, where the police criminals are all the same object
  • After the criminal shouts, he will lock the criminal object. Then he calls the response from the police object. After the police shout, he will also lock his own police object and wait for the criminal's response. At this time, both objects are locked and waiting for the other party's response, which will lead to a deadlock.

Solve

Do not call another locked method in one locked method

Multithreaded communication problem

Some resources are shared by some threads. When a thread is using these resources, another thread that needs resources should wait using the wait() method until the first thread uses the resources and wakes up the waiting threads using the notify() method to achieve resource scheduling.

Example

  public static void main(String[] args) {
        Food f = new Food();
        new Cook(f).start();
        new Waiter(f).start();
    }
    static  class Cook extends Thread{// Chefs
        private Food f;
        public Cook(Food f){// Get food objects
            this.f=f;
        }

        @Override
        public void run() {
            try {
            for(int i = 0 ;i< 10;i++){//Make 10 dishes of steamed dumplings and mixed noodles
                if(i%2==0){
                    f.setNameAndPrice("Steamed dumpling","7 element");
                }else {
                    f.setNameAndPrice("Noodles","5 element");
                }
            } } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    static  class Waiter extends  Thread{// Server class
        private Food f;

        public Waiter(Food f) {
            this.f = f;
        }

        @Override
        public void run() {
           for(int i=0;i<10;i++){// Take away the cook's dishes
               try {
                   Thread.sleep(100);// Avoid end too fast
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               f.get();
           }
        }
    }
    static  class Food{
        String name;
        String price;

 public  void setNameAndPrice( String name,String price) throws InterruptedException {
 // Chef production process: label-rest 0.1 seconds-label price
            this.name= name;
            Thread.sleep(100);//Adding sleep makes problems easier
            this.price=price;
        }
        public void  get(){// Server take away
            System.out.println(this.name+this.price);
        }
    }

Result

Mix dough for 7 yuan
 Steamed dumplings $5
 Mix dough for 7 yuan
 Steamed dumplings $5
 Mix dough for 7 yuan
 Steamed dumplings $5
 Mix dough for 7 yuan
 Steamed dumplings $5
 Mix dough for 7 yuan
 Mix noodles for 5 yuan

Analysis

If the waiter takes away the food during the chef's production process, the discrepancy between the above prices may occur.
Adding a synchronization lock can really solve the problem of data security. However, there may be situations where the chef keeps cooking and the server thread can't grab the time to finish the dish. The wait() and notify methods are needed

Solve

Modify the set and get methods with synchronized and wake up the waiter at the end of the set method to let the chef sleep; wake up the chef at the end of the get method to let the waiter sleep

package xzk.chapter4.section5;

public class Eat {
    public static void main(String[] args) {
        Food f = new Food();
        new Cook(f).start();
        new Waiter(f).start();
    }
    static  class Cook extends Thread{// Chefs
        private Food f;
        public Cook(Food f){// Chef's food object
            this.f=f;
        }

        @Override
        public void run() {
            try {
            for(int i = 0 ;i< 10;i++){// Make 10 portions of food, 5 steamed dumplings and 5 noodles
                if(i%2==0){
                    f.setNameAndPrice("Steamed dumpling","7 element");
                } else {
                    f.setNameAndPrice("Noodles","5 element");
                }
            } } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    static  class Waiter extends  Thread{// Server class
        private Food f;

        public Waiter(Food f) {
            this.f = f;
        }

        @Override
        public void run() {
           for(int i=0;i<10;i++){// End course (name and price output)
               try {
                   Thread.sleep(100);// Avoid end too fast
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               try {
                   f.get();
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
            System.out.println("End");
           this.interrupt();
        }
    }
    static  class Food{// Food
        String name;
        String price;
        private  int count =0;
        public  synchronized void setNameAndPrice( String name,String price) throws InterruptedException {
            // Food preparation methods
                this.name = name;
                Thread.sleep(100);//Joining sleep makes communication problems easier
                this.price = price;
                count++;

                this.notifyAll();
                this.wait();

        }
        public synchronized void  get() throws InterruptedException {// Serving method

                System.out.println(this.name + this.price);
                count++;
                this.notifyAll();
                //this.wait() //Using a parameterless wait method will keep the server process dormant after the last call to the get method
                this.wait(500);// A wait of 0.5 seconds should be used, so that neither the program nor an infinite wait occurs

            }
        }
}

Tags: REST

Posted on Wed, 17 Jun 2020 12:04:57 -0400 by cliftonbazaar