当前位置:网站首页>A detailed explanation of synchronized

A detailed explanation of synchronized

2022-06-12 23:56:00 < I can't do anything;

5.3 synchronized

1 Underlying principle

synchronized Underlying principle = java Object head markword + Operating system objects monitor

The head of the object Mark word:
[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-VpiXqROL-1643373380693)(Java Interview question summary .assets/image-20220128191854648.png)]

Monitor structure :

// Some properties 
ObjectMonitor() {
    _count        = 0;  // Lock counter   Number of entries 
    _owner        = NULL;
    _WaitSet      = NULL; // be in wait Thread in state , Will be added to _WaitSet
    _EntryList    = NULL ; // Waiting lock block Thread in state , Will be added to the list 
  }

Every Java Objects can be associated with a Monitor object , If you use synchronized Lock the object ( heavyweight ) after , Of the object's head Mark Word It is set to point to Monitor Object pointer
[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-Eu1r5jnS-1643373380694)(Java Interview question summary .assets/image-20220128192028194.png)]

1 synchronized Whether it's added to synchronized code blocks or methods , Effects are applied to objects , The principle is to lock an object
2 How to give this obj Locked ? When a thread Thread-1 When you want to execute code for a critical section , First it will pass obj Object's markword Point to one monitor Lock object
3 When Thread-1 Thread hold monitor After the object , It will monitor Medium owner Variable set to current thread Thread-1, Simultaneous counter count+1 Indicates that the current object lock is acquired by a thread .
4 When another thread Thread-2 When you want to execute code in a critical area , To judge monitor Object properties Owner Is it null, If null,Thread-2 The thread holds the object lock and can execute the code in the critical area , If not for null,Thread-2 The thread will be put into monitor Of EntryList Blocking the queue , In a blocking state Blocked.
5 When Thread-0 Finish executing the code in the critical area , Will release monitor( lock ) And will owner Variable set to null, And a calculator count-1, And notify EntryList Blocking threads in the queue , Wake up the thread inside

1》 synchronized When acting on a code block :

The bottom of it is through monitorenter、monitorexit Instructions to achieve

monitorenter:

  • Each object is a monitor lock (monitor), When an object is occupied, it is locked
  • **monitor Number of entries ( Lock counter )** by 0 Time represents no thread occupation , When a thread enters , The number of entries is set to 1, And the thread is monitor The owner of the owner
  • When the incoming thread already has the monitor, be monitor Number of entries +1
  • If it's time to monitor Occupied by another thread , Then the thread enters monitor In the blocking queue , wait for monitor The number of entries is 0

monitorexit:

  • perform monitorexit The thread of must be objectref The corresponding monitor holder
  • perform monitorexit after ,monitor Entry minus 1, If the number of entries is reduced to 0, The thread releases monitor

2》synchronized When acting on methods :

  • Compared to the normal method , There are more constant pools ACC_SYNCHRONIZED Identifier .JVM It is based on the identifier to achieve method synchronization
  • When a method is called , The call instruction will check the method's ACC_SYNCHRONIZED Whether the access flag is set , If set , Execution thread will get first monitor, Method body can only be executed after obtaining success , Release after method execution monitor
  • During method execution , No other thread can get the same monitor object .
2 Three ways of implementation
Act on example method
public class Test8 implements Runnable {
    

    // Static variables   A critical region 
    static int count = 0;

    //synchronized Decorated instance method 
    public synchronized void add() {
    
        count++;
    }

    @Override
    public void run() {
    
        // Thread body 
        for (int i = 0; i < 1000; i++) {
    
            add();
        }
    }

    public static void main(String[] args) throws InterruptedException {
    
        Test8 test8 = new Test8();
        // Multiple threads operate on an instance object 
        Thread thread1 = new Thread(test8);
        Thread thread2 = new Thread(test8);
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(count); //2000
    }
}

The above code simulates two threads operating on a shared variable count, Respectively for count Carry out self addition 1000, The end result is 2000.

because count++ It's not an atomic operation , It is divided into reading the value first and adding 1 Two step operation , So when executing concurrently , If not used synchronized Decorated instance method , Then the final result is likely to be less than 2000 Of

problem : There is only one instance object synchronized lock , If there are multiple instance objects operating on a shared variable ,synchronized Locks do not guarantee thread safety , For example, the above code's main Method modified to :

public static void main(String[] args) throws InterruptedException {
    
    Thread thread1 = new Thread(new Test8());
    Thread thread2 = new Thread(new Test8());
    thread1.start();
    thread2.start();
    thread1.join();
    thread2.join();
    System.out.println(count); // The final result will be less than 2000
}

The way to solve this problem is to synchronized Acting on static add Method , In this case , Object lock on the current class object , No matter how many instance objects are created , Class has only one , In this case, the object lock is the only one

Act on static methods

When synchronized When acting on a static method , Its lock is the current class class Object lock . Because static members do not belong exclusively to any instance object , It's a class member , So by class Object locks can control the concurrent operation of static members

public class Test8 implements Runnable {
    

    // Static variables   A critical region 
    static int count = 0;

    //synchronized Modified static method 
    public static synchronized void add() {
    
        count++;
    }

    @Override
    public void run() {
    
        // Thread body 
        for (int i = 0; i < 1000; i++) {
    
            add();
        }
    }

    public static void main(String[] args) throws InterruptedException {
    
        Thread thread1 = new Thread(new Test8());
        Thread thread2 = new Thread(new Test8());
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(count); // The end result is 2000
    }
}
Works on synchronized code blocks

When a method is big , Locking the entire method directly can be time-consuming ; Synchronous code can be used to lock a small part of the code in a method

synchronized Static code blocks cannot be decorated

notes : Use synchronized When locking synchronized code blocks , The instance object of multiple threads must also be the same , Cannot act on multiple instance objects

public class Test8 implements Runnable {
    
    // Global static instance 
    static Test8 test8=new Test8();

    // Static variables   A critical region 
    static int count = 0;

    //synchronized Decorated instance method 
    public void add() {
    
        // You can directly lock the specified instance synchronized (test8)
        // You can also lock the incoming this example 
        synchronized (this) {
    
            count++;
        }
    }

    @Override
    public void run() {
    
        // Thread body 
        for (int i = 0; i < 1000; i++) {
    
            add();
        }
    }

    public static void main(String[] args) throws InterruptedException {
    
        Thread thread1 = new Thread(test8);
        Thread thread2 = new Thread(test8);
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(count); //2000
    }
}
3 synchronized Upgrade mechanism

JDK 1.6 Before ,synchronized It's also a heavyweight lock . but JDK1.6 Then, bias lock and lightweight lock are introduced , Since then, there have been four lock states : unlocked 、 Biased locking 、 Lightweight lock 、 Heavyweight lock

Lock escalation is irreversible
[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-4egQROu8-1643373380695)(Java Interview question summary .assets/image-20220128201806521.png)]

1》 unlocked

No locking of resources , All threads can access and modify the same resource , But only one thread can modify successfully , Other threads will continue to loop , Until the modification is successful

2》 Biased locking

From the first time to synchronized Block of code , Lock objects become biased locks . And the lock will not be released after the synchronization code is executed

Rely only once CAS Atomic directive , Detect when entering and exiting the synchronization zone for the second time Mark Word Whether there are biased locks pointing to the current thread stored in .

The deflection lock only encounters Other threads try to compete for biased locks when , The thread holding the biased lock will release the lock

3》 Lightweight lock

When the lock is biased towards the lock , It's accessed by another thread , The biased lock will be upgraded to a lightweight lock , Other threads try to acquire the lock by spinning , Threads don't block , To improve performance

There are two main ways to obtain lightweight locks :

  • When the deflection lock function is turned off
  • Due to multiple threads ( Two or more ) Competition for biased locks causes biased locks to be upgraded to lightweight locks

4》 Heavyweight lock

** Busy etc. :** A thread holds a lock , Other threads can only be consumed in place CPU, Can't perform any effective task , This phenomenon is called busy waiting (busy-waiting), Lightweight lock spin is busy waiting

If the number of spins exceeds 10 Time , Will upgrade the lock heavyweight lock . When a subsequent thread attempts to acquire a lock , It is found that the lock occupied is a heavyweight lock , Then hang yourself up ( Instead of waiting ), Waiting for the future to be awakened .

原网站

版权声明
本文为[&lt; I can't do anything;]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202280603123337.html