The use of synchronized, wait, notify has notify All

Keywords: Java less

Foreword: About synchronized, wait, notify already notify all people should not be unfamiliar, now I roughly say my understanding.

One: synchronized

Synchronized Chinese interpretation is synchronized, so what is synchronization? Interpretation is the mechanism used to control the relative sequence of operations between different threads in the program. Generally speaking, it is two points. First, there must be multi-threading. Second, when multiple threads compete for a resource at the same time, there will be sequence. There are three ways to write synchronized in java

  • The first is:
    • Written before the general aspect, this representation locks the instance object.
  • Second species:
    • Written before static methods, this representation locks class objects
  • Third species:
    • Written in code blocks, locks are objects configured in Synchonized parentheses (either instance objects or class objects)

Generally speaking, there are two kinds, one is the lock instance object, the other is the lock class object.

Lock instance object is that when multiple threads operate this instance object at the same time, they must first acquire the lock. If they cannot acquire the lock, they must be in a waiting state. The difference between lock instance object and lock instance object is that when multiple threads operate at the same time, any object instantiated with this kind of object must acquire the lock to operate. A simple example

For example, if a group of people go to cook, as long as people have to wait in line, one by one to cook. Whoever you are, you can return the dishes to their original place after you finish your meal. But at this time, different people may eat different fast or slow, but they must eat first and then deliver the dishes. Now let's write a piece of code and compare it.

public class RunnableTest implements Runnable {

    private synchronized  void testSyncMethod() {
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getId() + "testSyncMethod:" + i);
        }
    }

    public void run() {
     testSyncMethod();
    }

    public static void main(String[] args) {
        ExecutorService exec = Executors.newFixedThreadPool(2);
        RunnableTest rt = new RunnableTest();
        RunnableTest rt1 = new RunnableTest();
        exec.execute(rt);
        exec.execute(rt1);
        exec.shutdown();
    }

According to our theory, the output must be in disorder. Pictured

public class RunnableTest implements Runnable {
    private void testSyncBlock() {
        synchronized (RunnableTest.class) {
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getId()+"testSyncBlock:" + i);
            }
        }
    }
    public void run() {
     testSyncBlock();
    }
    public static void main(String[] args) {
        ExecutorService exec = Executors.newFixedThreadPool(2);
        RunnableTest rt = new RunnableTest();
        RunnableTest rt1 = new RunnableTest();
        exec.execute(rt);
        exec.execute(rt1);
        exec.shutdown();
    }
}

And the input result of this code must be orderly. as follows

So we are thinking about a problem, if class A has two methods, if we add synchronized before one of them, which means that another method of calling this class by other threads also needs to acquire locks to execute, and another method only needs to read, so the performance will be greatly reduced, so we try our best to be less in front of the method in actual development. Join synchronized, so what should we do? Since it is a real object, we only need to add a class, lock this class, just let a method of the class lock. The following code for ok is as follows

public class A {
    private Object obj="123";
    public  void a(){
        synchronized (obj) {
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread() + "a:" + i);
            }
        }
    }
    public void b(){
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread() + "b:" + i);
            }

    }
}
public class B implements Runnable{
    private A a;
    public B(A a){
        this.a=a;
    }

    public void run() {
        a.b();
    }
}
public class C implements Runnable {
    private A a;
    public C(A a){
        this.a=a;
    }
    public void run() {
        a.a();
    }
}
public class E implements Runnable{
    private A a;
    public E(A a){
        this.a=a;
    }
    public void run() {
        a.a();
    }
}
public class D {
    public static void main(String[] args) {
        A a=new A();
        ExecutorService executorService= Executors.newCachedThreadPool();
        executorService.execute(new E((a)));
        executorService.execute(new B(a));
        executorService.execute(new C(a));
        executorService.shutdown();
    }
}

According to our theory, the execution order of this code is the first thread and the second thread is out of order. The third thread must wait for the first thread to finish executing before it can. The test results also demonstrate our theory as follows.

Two: wait, notify already notify all

wait, notify, notify All are attributes of Object objects, not threads. Let's first explain one of these three important concepts.

Wait: Make the thread holding the object hand over control of the object and then wait (which is important, that is to say, when the wait is called, the lock is released and the wait state is kept)

Notfy: Notify that a thread waiting for control of the object can continue to run (this is to get the lock, start its own program, and finally release the lock through notify, and wake up the waiting thread)

NotfyAll: Notifies all threads waiting for control of this object to continue running (just as above, it wakes up all waiting threads to continue executing)

This is good. From the above explanation, we can see that communication between threads can be done through wait and notify. When thread A has finished processing, it notifies thread B to execute, and thread A can continue to execute after thread B has finished executing. ok Let's use an example to illustrate.

 

public class Temp {
    int count=0;
    public void waiter() throws InterruptedException {
        synchronized (this) {
               System.out.println("wait for");
               wait();
               System.out.println(this.count);
        }
    }
    public void notifyer() throws InterruptedException {
        synchronized (this){
            TimeUnit.SECONDS.sleep(1);
            System.out.println("awaken");
            for (int i=0;i<10;i++){
                System.out.println(Thread.currentThread()+"notifyer:"+i);
                count+=i;
            }
            notify();
        }
    }

public class Waiter implements Runnable{
    private Temp temp;
    public Waiter(Temp temp){
        this.temp=temp;
    }
    public void run() {
        try {
            temp.waiter();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class Notifyer implements Runnable{
    private Temp temp;
    public Notifyer(Temp temp){
        this.temp=temp;
    }
    public void run() {
        try {
            temp.notifyer();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

   public static void main(String[] args) {
        Temp temp=new Temp();
        ExecutorService executorService= Executors.newCachedThreadPool();
        executorService.execute(new Waiter(temp));
        executorService.execute(new Notifyer(temp));
        executorService.shutdown();
    }

The purpose of adding sleep 1s in notify is to make the thread waiter execute first more clearly.

Talk about the difference between wait and sleep

Distinction 1: Object locks are released during wait

Difference 2: You can restore execution from wait by notify and notify All, or Ling's command expires. If wait does not accept any parameters, the wait will wait wirelessly until the thread receives notify or notifyall messages

Posted by quiettech on Sun, 07 Apr 2019 14:42:31 -0700