Compilation of interview knowledge related to Java concurrent lock

Java lock has pessimistic lock and optimistic lock, optimistic lock is realized by cas, and pessimistic lock has ReentrantLock and synchronized. ReentrantLock features: time lock waiting, interruptible lock waiting, block-less structure lock, multiple condition variables or lock voting, etc. Synchronized has only one advantage, it is convenient and simple to use, and there is no need to actively release the lock. Both ReentrantLock and synchronized are reentrant locks.

One, synchronized lock

1. Lock upgrade
The 4 states of the lock: no lock state, biased lock state, lightweight lock state, heavyweight lock state (from low to high)

(1) Bias lock:

Why introduce biased locks?

Because after a lot of research by the authors of HotSpot, it is found that most of the time there is no lock competition. Often a thread acquires the same lock multiple times. Therefore, if there is a competition for the lock each time, it will increase a lot of unnecessary costs. To reduce the cost of acquiring the lock, the bias lock was introduced.

Upgrade of bias lock

When thread 1 accesses the code block and acquires the lock object, the threadID of the biased lock will be recorded in the java object header and stack frame, because the biased lock will not actively release the lock, so when thread 1 acquires the lock again in the future, it needs to compare the current Whether the thread ID of the thread is the same as the threadID in the Java object header. If they are the same (or thread 1 acquires the lock object), there is no need to use CAS to lock and unlock; if they are inconsistent (other threads, such as thread 2 must compete for the lock object, and bias The lock will not be released actively, so the threadID of thread 1 is still stored), then you need to check whether thread 1 recorded in the Java object header is alive. If it does not survive, the lock object is reset to a lock-free state, and other threads (thread 2) You can compete to set it as a biased lock; if it survives, then immediately look up the stack frame information of the thread (thread 1), if you still need to continue to hold the lock object, then pause the current thread 1, cancel the biased lock, and upgrade to lightweight Level lock, if thread 1 no longer uses the lock object, then the lock object state is set to the unlocked state, and the new thread is re-biased.

Cancellation of bias lock:

The bias lock is turned on by default, and the start time is generally a few seconds slower than the application startup. If you don't want this delay, you can use -XX:BiasedLockingStartUpDelay=0;

If you don't want a biased lock, you can set it by -XX:-UseBiasedLocking = false;

(2) Lightweight lock

Why introduce lightweight locks?

The lightweight lock considers the situation where there are not many threads competing for the lock object, and the threads hold the lock for a short time. Because blocking the thread requires the CPU to switch from the user mode to the kernel mode, the cost is relatively high. If the lock is released soon after blocking, the cost is not worth the price. Therefore, at this time, simply don't block the thread and let it spin. This waits for the lock to be released.

When will lightweight locks be upgraded to heavyweight locks?

When thread 1 acquires a lightweight lock, it first copies the object header MarkWord of the lock object to the space created in the stack frame of thread 1 for storing lock records (called DisplacedMarkWord), and then uses CAS to transfer the object header The content is replaced with the address of the lock record (DisplacedMarkWord) stored in thread 1;

If thread 1 copies the object header at the same time (before thread 1CAS), thread 2 also prepares to acquire the lock, and copies the object header to the lock record space of thread 2, but in thread 2CAS, it is found that thread 1 has already put the object header If the CAS of thread 2 fails, then thread 2 tries to use the spin lock to wait for thread 1 to release the lock.

But if the spin time is too long, it won’t work, because spin consumes the CPU, so the number of spins is limited, such as 10 or 100 times. If the number of spins reaches Thread 1, the lock has not been released, or Thread 1 is still executing, and thread 2 is still spinning and waiting. At this time, another thread 3 comes to compete for this lock object, then the lightweight lock will expand into a heavyweight lock at this time. Heavyweight locks block all threads except those that own the lock to prevent the CPU from idling.

 

*Note: In order to avoid useless spin, once a lightweight lock is expanded to a heavyweight lock, it will not be downgraded to a lightweight lock; a biased lock cannot be downgraded to a biased lock if it is upgraded to a lightweight lock. In a word, the lock can be upgraded but not downgraded, but the biased lock state can be reset to the unlocked state.

(3) The advantages and disadvantages of these types of locks (biased locks, lightweight locks, heavyweight locks)

2. Lock coarsening. In
theory, the scope of the synchronization block should be as small as possible, and only synchronize in the actual scope of the shared data. The purpose of this is to reduce the number of operations that need to be synchronized as much as possible and shorten the blocking Time, if there is lock contention, then the thread waiting for the lock can also get the lock as soon as possible. 
However, locking and unlocking also consumes resources. If there is a series of continuous locking and unlocking operations, it may cause unnecessary performance loss. 
Lock coarsening is to connect multiple consecutive locking and unlocking operations together and expand into a larger range of locks to avoid frequent locking and unlocking operations.

3. Lock elimination
Java virtual machine during JIT compilation (it can be simply understood as compiling when a certain piece of code is about to be executed for the first time, also known as just-in-time compilation), through scanning the running context, after escape analysis, it is impossible to remove There are locks that compete for shared resources. In this way, unnecessary locks can be eliminated, which can save meaningless lock time

Two, ReentrantLock lock

 

 



Reference: https://blog.csdn.net/tongdanping/article/details/79647337 

Guess you like

Origin blog.csdn.net/noob9527/article/details/90698596