Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the core principle of synchronized lightweight lock in Java?

2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article will explain in detail what is the core principle of synchronized lightweight lock in Java. The editor thinks it is very practical, so I share it with you as a reference. I hope you can get something after reading this article.

1. The principle of lightweight lock

The main purpose of introducing lightweight lock is to reduce the performance loss caused by heavy lock through CAS mechanism under the condition that multi-thread competition is not fierce. Heavy locks use the underlying mutex lock (Mutex Lock) of the operating system, which will cause threads to switch frequently between user mode and kernel state, resulting in greater performance loss.

Lightweight lock usage scenario: if an object has multiple threads to lock, but the locking time is staggered (that is, there is no competition), then lightweight locks can be used to optimize.

The purpose of lightweight locks is to avoid using mutexes at the operating system level as much as possible because of their poor performance. Thread blocking and awakening requires CPU to change from user mode to kernel state. Frequent blocking and awakening is a heavy task for CPU. At the same time, we can find that the locking state of many object locks only lasts for a short period of time, such as the self-adding operation of integers, it is obviously not worthwhile to block and wake up the thread in a very short time, so a lightweight lock is introduced. Lightweight lock is a kind of spin lock, because JVM itself is an application, we hope to solve the problem of thread synchronization through spin at the application level.

Public class Main {static final Object obj = new Object (); public static void main (String [] args) {Thread thread = new Thread (()-> {method1 ();}); thread.start ();} public static void method1 () {synchronized (obj) {/ / synchronous block A method2 () }} public static void method2 () {synchronized (obj) {/ / Sync Block B}

The execution of lightweight locks:

Before the lock grabbing thread enters the critical section, if the built-in lock is not locked, JVM will first establish a lock record (Lock Record) in the stack frame of the lock grabbing thread to store a copy of the object Mark Word

The lock grab thread will then use the CAS spin operation to try to update the ptr_to_lock_record (lock record pointer) of the Mark Word with the lock object header in the lock thread stack frame to the address of the lock record in the stack frame of the lock grab thread. If the update is executed successfully, the thread has the object lock. JVM then changes the lock flag bit in Mark Word to 00 (lightweight lock flag), indicating that the object is in a lightweight locked state. After the lock grab is successful, JVM will save the original lock object information (such as hash code, etc.) in the Displaced Mark Word (misplaced Mark Word) field of the lock grab thread lock record, and then point the owner pointer of the lock record in the lock grab thread to the lock object.

Lock records are private to threads, and each thread has its own lock record. After the lock record is created, the Mark Word of the built-in lock object is copied to the Displaced Mark Word field of the lock record. Why is that? Because the structure of the MarkWord of the built-in lock object will change, the MarkWord will have a pointer to the lock record, instead of storing information such as the hash code of the lock object in the unlocked state, so the information must be temporarily stored for later use when the lock is released.

(1) before the lock grabbing thread enters the critical area, if the built-in lock is not locked, JVM will first establish a lock record (Lock Record) in the stack frame of the lock grabbing thread. The stack frame of each thread will contain the structure of a lock record, and the mark word of the locked object can be stored internally.

(2) the lock grabbing thread will use the CAS spin operation to try to update the ptr_to_lock_record (lock record pointer) of the mark word with the built-in lock object header to the address of the lock record in the lock thread stack frame. If the update is executed successfully, the thread will have the object lock. Jvm then changes the lock flag bit in the mark word to 00, indicating that the object is in a lightweight locked state.

After the lock grab is successful, jvm will save the original lock object information (such as hash code, etc.) in mark word in the Displaced Mark Word field of the lock grab thread lock record, and then point the owner pointer of the lock record in the lock grab thread to the lock object.

The 64-bit mark word structure is shown in the table:

After the lightweight lock preemption succeeds, the lock record and the state of the object header are shown in the figure:

Lock records are private to threads, and each thread has its own lock record. After the lock record is created, the Mark Word of the built-in lock object is copied to the Displaced Mark Word field of the lock record. Why is that? Because the structure of the mark word of the built-in lock object will change, the mark word will have a pointer to the lock record, instead of storing information such as the hash code of the lock object in the unlocked state, so the information must be temporarily stored for later use when the lock is released.

(3) if cas fails, there are two situations:

If another thread already holds the lightweight lock of the Object, it indicates that there is competition and enters the lock expansion process.

If you performed the synchronized lock reentry yourself, add another Lock Record as the count of the reentrant

(4) when exiting the synchronized code block (when unlocking), if there is a lock record with a value of null, it indicates that there is reentry, and the lock record is reset, indicating that the reentry count is reduced by one.

two。 Classification of lightweight locks

There are two main types of lightweight locks: ordinary spin lock and adaptive spin lock.

1. Ordinary spin lock

The so-called ordinary spin lock means that when a thread competes for the lock, the lock-grabbing thread will cycle and wait in place instead of being blocked, and the lock-grabbing thread will not be able to acquire the lock until the thread that owns the lock releases the lock.

Description:

Locks consume CPU while waiting in a loop in place, which is equivalent to executing an empty loop that does nothing. So lightweight locks are suitable for scenarios where the critical section code takes a short time, so that the thread can acquire the lock after a short wait in place. By default, the number of spins is 10, which you can change with the-XX:PreBlockSpin option.

2. Adaptive spin lock

The so-called adaptive spin lock means that the number of spins of the empty loop of the waiting thread is not fixed, but will dynamically change the number of spins according to the actual situation. the number of spins is determined by the spin time of the previous time on the same lock and the state of the lock owner. The general principle of adaptive spin lock is:

If the lock-grabbing thread successfully acquired the lock before the same lock object, jvm will assume that the spin is likely to succeed again, thus allowing the spin to wait for a relatively longer period of time.

Adaptive spin solves the problem of "uncertain lock competition time". Adaptive spin assumes that different threads hold the same lock object for almost the same time, and the degree of competition tends to be stable. The general idea is to adjust the time of the next spin according to the time and result of the last spin.

The lightweight lock of JDK 1.6 uses a normal spin lock and needs to be opened manually using the-XX:+UseSpinning option.

After JDK 1.7, the lightweight lock uses an adaptive spin lock, the JVM opens automatically when it starts, and the spin time is automatically controlled by JVM.

3. The expansion of lightweight locks

What's the problem with lightweight locks?

Although the execution time of most critical section code is very short, there will also be critical section code that executes very slowly. The critical section code takes a long time to execute, and during its execution, other threads are spinning and waiting in place, which consumes CPU empty. Therefore, if there are many threads competing for this synchronization lock, there will be multiple threads waiting in place to continue the empty loop to consume CPU (empty spin), which will cause a lot of performance loss.

Lightweight locks are intended to reduce the probability of multithreads entering the underlying mutex of the operating system, not to replace the operating system mutex. Therefore, in a highly competitive scenario, lightweight locks will expand to heavyweight locks based on operating system kernel mutexes.

If the CAS operation fails in the process of trying to add a lightweight lock, there is a situation where another thread adds a lightweight lock to this object (there is competition), and lock expansion is needed to turn the lightweight lock into a heavy lock.

(1) when Thread-1 adds a lightweight lock, Thread-0 has already added a lightweight lock to the object

When Thread-1 plus lightweight lock fails, enter the lock expansion process, that is, apply a Monitor lock for the lock object, let the lock object point to the heavyweight lock address, and then enter the EntryList BLOCKED of Monitor.

When Thread-0 exits the synchronization block to unlock, use cas to restore the value of mark word to the object header, which fails. At this point, you will enter the heavyweight unlocking process, that is, find the Monitor object according to the Monitor address, set Owner to null, and wake up the BLOCKED thread in the EntryList.

This is the end of this article on "what is the core principle of synchronized lightweight locks in Java". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, please share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report