Synchronized in a past life

As is known to all, Synchronized locking before JDK1.6 directly uses the mutex provided by Linux to acquire the lock. When a thread fails to acquire the lock, it will block the current thread sleep until it reaches the sleep limit or is actively woken up and acquires the lock again until it acquires the lock. Whether mutex or Sleep of Linux is called, there will be a switch from CPU user state to kernel state when a thread acquires a lock. In fact, sometimes only one or two threads compete alternately for lock resources, and still need to use system call, which undoubtedly consumes a lot of CPU resources. Therefore, Synchronized locking is optimized in JDK1.6. According to the degree of competition for locks are divided into: biased locks, lightweight locks, heavyweight locks.

Definition of different locks after lock optimization

Biased locking

The contention for a Synchronized modified lock object exists only in one thread, which means that the lock object can only be held by one thread. We define the current moment as favoring the current thread. The thread ID of the Mark Word is changed by CAS. The thread ID of the Mark Word is changed by CAS. The thread ID of the Mark Word is changed by CAS. Actually, just define biased locking here, only one thread for locks, but the reality is likely, there will be multiple threads competing for the lock, if open the can bias, then the CAS ensure that only one thread can get biased locking, while the other CAS failed thread will go to lock to withdraw, acquiring a lock walk lightweight locking process again, fail again will expand into heavy lock, So CAS is for concurrency locking.

Lightweight lock

The common definition of lightweight locking is that two threads are interlocking, which I think is a little vague because interlocking is not easy to define. Below, I use several alternate execution experiments to prove that two threads can get three cases of alternate execution, namely biased lock, lightweight lock and heavyweight lock.

Get bias lock

public static void main(String[] args) throws InterruptedException { Object o = new Object(); Thread t1 = new Thread(() -> { synchronized (o){ System.out.println("t1-----"+ClassLayout.parseInstance(o).toPrintable()); }}); Thread t2 = new Thread(() -> { synchronized (o){ System.out.println("t2----"+ClassLayout.parseInstance(o).toPrintable()); }}); t1.start(); t1.join(); TimeUnit.SECONDS.sleep(0); t2.start(); }Copy the code

Get the lightweight lock

public static void main(String[] args) throws InterruptedException { Object o = new Object(); Thread t1 = new Thread(() -> { synchronized (o){ System.out.println("t1-----"+ClassLayout.parseInstance(o).toPrintable()); }}); Thread t2 = new Thread(() -> { synchronized (o){ System.out.println("t2----"+ClassLayout.parseInstance(o).toPrintable()); }}); t1.start(); t1.join(); //TimeUnit.SECONDS.sleep(0); t2.start(); }Copy the code

Get the heavyweight lock

public static void main(String[] args) throws InterruptedException { Object o = new Object(); Thread t1 = new Thread(() -> { synchronized (o){ System.out.println("t1-----"+ClassLayout.parseInstance(o).toPrintable()); }}); Thread t2 = new Thread(() -> { synchronized (o){ System.out.println("t2----"+ClassLayout.parseInstance(o).toPrintable()); }}); t1.start(); //t1.join(); TimeUnit.SECONDS.sleep(1); t2.start(); }Copy the code

So I think lightweight locking should be the case when the lock flag is no lock (001) is lightweight locking. And I thinkLightweight locks do not spinTherefore, there is no such thing as a spin lock. However, Synchronized locks have spin operation, that is, when the lightweight CAS fails to modify the Lock Record address, it expands into a heavyweight Lock, and does not directly join the team or acquire the Lock through Mutex. Instead, it will continue to acquire locks through spin CAS, which is also a referenceJUC RentrantLockLock process.

Heavyweight lock

Synchronized eventually bulges into a heavyweight lock when two or more threads are competing for it. Note that we are talking about the end, either directly or heavyweight locks. This article focuses on the locking process, so the composition of the object header is not explained.

Synchronized flowchart as I understand it