A synchronized lock is the object of the resource class in which the synchronized method resides. In other words, it is impossible for two threads to access the resource class at the same time. Only one thread is allowed to access one synchronized method at a time

Write a resource class with two methods, and then repeat the test, the main method has two threads to operate on the resource class, the next to write the resource class, check the call situation, for convenience, the two methods before the interval of 100 milliseconds

T1: standard access

class Phone{

    public synchronized void sendEmail(a){
        System.out.println("send Email~~~");
    }
    
    public synchronized void sendMsg(a){
        System.out.println("send Msg~~~"); }}public class _Eight lock theory{
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();
        / / 1
        new Thread(()->{ phone.sendEmail(); },"A").start();
        Thread.sleep(100);
        / / 2
        new Thread(()->{ phone.sendMsg(); },"B").start(); }}Copy the code

Thread.sleep(100); thread.sleep (100); “, but in fact, it is not necessarily the CPU scheduling, synchronized modified way, the lock object is the method caller, because these two methods lock the same object, so the first call first execution.

T2: Pause the mail method for 3 seconds

class Phone{
    public  synchronized void sendEmail(a){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("send Email~~~");
    }
    
    public synchronized void sendMsg(a){
        System.out.println("send Msg~~~"); }}public class _Eight lock theory{
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();
        / / 1
        new Thread(()->{ phone.sendEmail(); },"A").start();
        Thread.sleep(100);
        / / 2
        new Thread(()->{ phone.sendMsg(); },"B").start(); }}Copy the code

Synchronized is an object lock

  • If there are multiple synchronized methods on an object and a thread calls one of them at any given time,
  • All other threads have to wait. In other words, only one thread can access synchronized methods at any given time.
  • The lock is on the current object this, and after this is locked, no other thread can access the current object’s other synchronized methods

T3: Add a normal method hello()

class Phone{
    public  synchronized void sendEmail(a){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("send Email~~~");
    }

    public synchronized void sendMsg(a){
        System.out.println("send Msg~~~");
    }

    public void hello(a){
        System.out.println("hello world!"); }}public class _Eight lock theory{
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();
        / / 1
        new Thread(()->{ phone.sendEmail(); },"A").start();
        Thread.sleep(100);
        / / 2
        new Thread(()->{ phone.hello(); },"B").start(); }}Copy the code

The mail method executes first and waits for 3 seconds. This time thread B does not wait for the mail method to complete before printing, but prints directly because Hello is not modified by synchronized

  • The normal method has nothing to do with synchronous locking

T4: Two mobile phones

class Phone{
    public  synchronized void sendEmail(a){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("send Email~~~");
    }

    public synchronized void sendMsg(a){
        System.out.println("send Msg~~~");
    }

    public void hello(a){
        System.out.println("hello world!"); }}public class _Eight lock theory{
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();
        Phone phone2 = new Phone();
        / / 1
        new Thread(()->{ phone.sendEmail(); },"A").start();
        Thread.sleep(100);
        / / 2
        new Thread(()->{ phone2.sendMsg(); },"B").start(); }}Copy the code

Print sendMsg of phone2 first and sendemail of phone 3s later, because the resource object is different.

  • When you switch to two objects, not the same instance, not the same lock, the situation immediately changes, and the two are unrelated

T5: Two static synchronization methods, same mobile phone

class Phone{
    public static synchronized void sendEmail(a){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("send Email~~~");
    }

    public static synchronized void sendMsg(a){
        System.out.println("send Msg~~~");
    }

    public void hello(a){
        System.out.println("hello world!"); }}public class _Eight lock theory{
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();
        Phone phone2 = new Phone();
        / / 1
        new Thread(()->{ phone.sendEmail(); },"A").start();
        Thread.sleep(100);
        / / 2
        new Thread(()->{ phone.sendMsg(); },"B").start(); }}Copy the code

Print sendEmail and sendMsg after 3s.

T6: Two static synchronization methods, two mobile phones

class Phone{
    public static synchronized void sendEmail(a){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("send Email~~~");
    }

    public static synchronized void sendMsg(a){
        System.out.println("send Msg~~~");
    }

    public void hello(a){
        System.out.println("hello world!"); }}public class _Eight lock theory{
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();
        Phone phone2 = new Phone();
        / / 1
        new Thread(()->{ phone.sendEmail(); },"A").start();
        Thread.sleep(100);
        / / 2
        new Thread(()->{ phone2.sendMsg(); },"B").start(); }}Copy the code



Still print the email first

In combination with T5 and T6, the static synchronization method is a class lock, rather than an object lock, i.e. the same bytecode object is locked

Synchronized is the basis for implementing synchronization: Every object (instance) in Java can be used as a lock, in one of three forms.

  • 1. For normal synchronization methods, the lock is the current instance object, and the lock is the current object this,
  • 2. For synchronized method blocks, lock objects configured in synchronized parentheses.
  • For statically synchronized methods, the lock is the class object of the current class

T7: a static synchronization method, a common synchronization method, the same mobile phone

 class Phone{
    public static synchronized void sendEmail(a){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("send Email~~~");
    }

    public  synchronized void sendMsg(a){
        System.out.println("send Msg~~~");
    }

    public void hello(a){
        System.out.println("hello world!"); }}public class _Eight lock theory{
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();
        Phone phone2 = new Phone();
        / / 1
        new Thread(()->{ phone.sendEmail(); },"A").start();
        Thread.sleep(100);
        / / 2
        new Thread(()->{ phone.sendMsg(); },"B").start(); }}Copy the code

Print sendMsg first, because sendEmail locks the template (static), sendMsg locks the class, and the two do not conflict.

T8: one static synchronization method, one common synchronization method, two mobile phones

class Phone{
    public static synchronized void sendEmail(a){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("send Email~~~");
    }

    public  synchronized void sendMsg(a){
        System.out.println("send Msg~~~");
    }

    public void hello(a){
        System.out.println("hello world!"); }}public class _Eight lock theory{
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();
        Phone phone2 = new Phone();
        / / 1
        new Thread(()->{ phone.sendEmail(); },"A").start();
        Thread.sleep(100);
        / / 2
        new Thread(()->{ phone2.sendMsg(); },"B").start(); }}Copy the code

Print sendMsg first, because sendEmail locks the template (static), sendMsg locks the template instance object, and operates on different objects, the two are not conflicting.

conclusion

Synchronized implements the basis for synchronization, and every object in Java can be used as a lock. There are three specific forms of expression:

  • 1: For normal methods, the lock is the current instance object.
  • 2: For statically synchronized methods, the lock is the class object of the current class.
  • 3: For synchronized method blocks, locks are objects configured in synchronized parentheses.

When a thread attempts to access a synchronized block of code, it must first acquire the lock and release it when it exits or throws an exception.

That is, when a non-statically synchronized method of an instance acquires a lock, the other non-statically synchronized methods of the instance must wait for the method that acquires the lock to release the lock. If the non-statically synchronized methods of another instance object use different locks than the non-statically synchronized methods of the instance object, they acquire their own locks without waiting for the non-statically synchronized methods of the acquired lock to release the lock.

Object locks and class locks (this/class) are two different objects, so there is no race condition between statically synchronized and non-statically synchronized methods. But once the static method acquires the lock, all other statically synchronized methods must wait for the method to release the lock.

conclusion

  • When a thread attempts to access a synchronized block of code, it must first acquire the lock and release it when it exits or throws an exception.
  • That is, if a common synchronization method of an instance acquires a lock, the other common synchronization methods of that instance must wait for the method that acquires the lock to release the lock.
  • However, the normal synchronization method of other instance objects uses a different lock than the normal synchronization method of this instance object.
  • So they can acquire their own locks without waiting for the normal synchronization methods of the instance objects to release the locks.

Static and normal synchronous locks do not interfere with each other

  • All statically synchronized methods use the same lock — the class object itself,
  • The two locks (this/class) are two different objects, so there are no static conditions between statically synchronized and non-statically synchronized methods.
  • But once a statically synchronized method acquires the lock, all other statically synchronized methods must wait for the method to release the lock.
  • Whether it’s between statically synchronized methods of the same instance object, or between statically synchronized methods of different instance objects, as long as they’re instance objects of the same class