Detailed explanation of synchronized use and underlying principles

In multithreaded programming, multiple threads may access the same shared, variable resource at the same time. We call this resource a critical resource; this resource may be: objects, variables, files, etc.

  • Sharing: Resources can be accessed by multiple threads at the same time
  • Variable: the resource can be modified during its life cycle

Questions that arise:

Because the process of thread execution is uncontrollable, it is necessary to use a synchronization mechanism to coordinate access to the variable state of the object

Locking role and lock definition classification

Locking purpose: serialized access to critical resources, that is, only one thread can access critical resources at the same time (synchronous exclusive access)
Insert picture description here

Insert picture description here

Detailed explanation of synchronized principle

Synchronized built-in lock is an object lock (the lock is an object instead of a reference), and the granularity is the object. It can be used to achieve synchronized and mutually exclusive access to critical resources and is reentrant.

  • Synchronous instance method, the lock is the current instance object
  • Synchronous class method, lock is the current class object, static method
  • Synchronous code block, the lock is the object inside the brackets

The underlying principle of synchronized

Synchronized is implemented based on the JVM built-in lock, implemented by the internal object Monitor (monitor lock), based on the entry and exit of the Monitor object implementation method and code block synchronization, the implementation of the monitor lock depends on the implementation of the Mutex lock (mutual exclusion lock) of the underlying operating system , It is a heavyweight lock with lower performance. Of course, JVM built-in locks have made major optimizations after version 1.5, such as Lock Coarsening, Lock Elimination, Lightweight
Locking, Biased Locking, Adaptive Spinning (Adaptive Spinning) and other technologies to reduce the overhead of lock operations, the concurrency performance of the built-in lock has been basically the same as that of Lock. After the synchronized keyword is compiled into bytecode, it will be translated into two instructions, monitorenter and monitorexit, at the start and end positions of the logic code of the synchronization block respectively.
Insert picture description here
Each synchronization object has its own Monitor (monitor lock), the locking process is shown in the figure below

Insert picture description here
The lock state is recorded in the object header (Mark Word) of each object. Let’s take a look at the memory layout of the object.

  • Object header: such as hash code, age of the object, object lock, lock status flag, bias lock (thread) ID, bias time, array length (array object), etc.
  • Instance data: when the object is created, the member variables, methods, etc. in the object
  • Alignment padding: The size of the object must be an integer multiple of 8 bytes.
    Insert picture description here
    The expansion and upgrade process of the lock

After JDK1.6, various optimizations have been made to the implementation of synchronized, such as spin locks, biased locks, and lightweight locks.

And turn on the bias lock by default

Turn on the bias lock: -XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0

Turn off the biased lock: -XX:-UseBiasedLocking

Insert picture description here

There are a total of four lock states, unlocked state, biased lock, lightweight lock and heavyweight lock. With the competition of locks, locks can be upgraded from biased locks to lightweight locks, and then upgraded heavyweight locks, but the upgrade of locks is one-way, which means that it can only be upgraded from low to high, and there will be no locks. Downgrade. The following picture shows the whole process of lock upgrade:
Insert picture description here

Note: Synchronized is reentrant. As the lock is upgraded, the optimization is relatively high. Compared with the lock of juc, the optimization space of synchronized is larger.

Must the object be allocated in the heap?
Not necessarily, if no object escape occurs, the object will be allocated on the stack

Coarsening of the lock

There are locks in the following 4 steps, and a total lock will be added after optimization

public void test1(){
    
    
    //jvm的优化,锁的粗化
    stb.append("1");
    stb.append("2");
    stb.append("3");
    stb.append("4");
}

Elimination of locks

public void test2(){
    
    
    //jvm的优化,JVM不会对同步块进行加锁
    synchronized (new Object()) {
    
    
        //伪代码:很多逻辑
        //jvm是否会加锁?
        //jvm会进行逃逸分析
    }
}

Guess you like

Origin blog.csdn.net/qq_37904966/article/details/112643302
Recommended