foreword
Keywords in Java synchronized
can be used as thread-safe synchronization locks in a multithreaded environment. This article does not discuss synchronized
the specific use, but studies the synchronized
underlying lock mechanism and the advantages and disadvantages of these locks.
1. Synchronized mechanism
synchronized
The keyword is a commonly used synchronization function in JAVA, which provides a simple and easy-to-use lock function. synchronized
There are three usages, namely:
- Used in ordinary methods, it can lock the current object.
- Used on static methods to lock classes
- Used on code blocks,
synchronized
the object in () is locked
Before JDK6, synchronized
the heavyweight locking system was used, and synchronized
the lock inflation mechanism was added later, which significantly improved the synchronized
efficiency of keywords.
Based on the synchronized
keywords, let's understand the next types of locks and explain synchronized
the lock expansion mechanism.
synchronized
Locks are unfair locks. And asynchronized
locked object or class is a lock.
In addition, all locks are stored in the Java object header. The Mark Word in the Java object header stores the object's HashCode, generation age and lock flag bit by default. That is to say, Mark Word records the status of the lock
2. Lock Expansion Mechanism and Several Types of Locks
Lock bloat is irreversible
2.1 Bias lock
synchronized
It is enabled by default after JDK1.6偏向锁
,synchronized
initially偏向锁
Performance: After a thread acquires the lock successfully, the thread ID will be recorded in the object header, and the thread acquires and releases the lock without any cost in the future. (because the lock is already bound to the thread and won't change until it is bloated), if other threads try to acquire the lock, 偏向锁
it will bloat as 轻量锁
.
Advantage: no cost to acquire and exit locks when only one thread is using the lock
Disadvantage: Intense lock competition will quickly escalate 轻量锁
, so maintaining 偏向锁
the process is a waste of computer resources. (However, because it 偏向锁
is very lightweight, there are not many wasted resources)
Summary: When only one thread uses synchronized
the lock, the lock used is 偏向锁
. If lock contention is intense, it can be disabled by configuring the JDK 偏向锁
.
2.2 Lightweight lock
If a lock is used by more than one thread, it
偏向锁
expands to轻量锁
Performance: When the thread is acquired 轻量锁
, it will directly CAS
modify the record of the lock in the object header. If the modification fails, it means that there is competition among multiple threads at this time, and 轻量锁
it will expand to 重量锁
.
Advantages: When there is no competition for the use of locks between threads, a single CAS
operation can acquire and exit locks
Cons: 偏向锁
Similar to
Summary: As long as a lock is acquired by more than one thread, 偏向锁
it will swell to 轻量锁
.
2.3 Weight lock
If a lock is in multi-thread competition, it
轻量锁
starts to spin. If the lock is not acquired after a certain number of spins, it expands to重量锁
(when there is competition,轻量锁
it will spin first, but it will eventually expand to重量锁
)
Performance: When the thread acquires 重量锁
, if the acquisition fails (that is, the lock has been acquired by other threads), it will be used 自适应自旋锁
, and the lock will not be acquired after a certain number of spins, and it will enter the blocking queue to wait.
Advantages: Unacquired locks enter the blocking queue, saving CPU resources. (Well, it doesn't feel like it has any advantages)
Disadvantage: 重量锁
It is implemented through the monitor inside the object. The essence of the monitor is to rely on the Mutex Lock implementation of the underlying operating system. The switching between threads of the operating system requires switching from user mode to kernel mode, and the switching cost is very high. high.
Summary: As long as a lock competes with multiple threads, 轻量锁
it will swell as 重量锁
.
spin lock
synchronized
, 轻量锁
, 重量锁
used 自适应自旋锁
for performance optimization
First introduce自旋锁
Performance: After the thread fails to acquire the lock, it will not enter the blocking wait, but will try to acquire the lock again, and so on, until the lock is acquired, or the spin ends, it will block and wait.
Problem solved: In some scenarios, threads hold locks for a very short time. After the thread fails to acquire the lock, if the thread enters the blocking, the thread context will be switched, and the time of the context switch may be higher than the time it takes for the thread to repeatedly try to acquire the lock. At this point, the thread waits in place to repeatedly acquire the lock. Instead, it has an advantage in performance.
shortcoming:
- A single-core CPU has no thread parallelism, and repeated attempts will cause the process to not continue to run.
- Repeated attempts lead to CPU usage, and if CPU resources are tight, performance will be degraded
- If the lock competition time is too long, not only there is no performance improvement, but also a lot of CPU resources are wasted.
Optimization: use 自适应自旋锁
. The adaptive spin lock will optimize and adjust the spin time according to the previous lock acquisition records to avoid unnecessary spins.