The previous two blogs analyzed the fair lock acquisition and release mechanism, this blog we will start to analyze the process of unfair lock acquisition and release.
Acquire unfair lock (based on JDK 11.0.5)
The process of acquiring locks is the same for unfair locks and fair locks. The difference between them is different mechanisms for trying to obtain locks. To put it simply, fair lock
uses a fair strategy (ordering and waiting according to the waiting queue) every time it tries to acquire a lock. Unfair lock
ignore the waiting queue, try to acquire the lock directly. If the lock is idle, you can acquire the status, then acquire the lock.
Next, let’s look at process to obtain the unfair lock.
1. lock()
lock()
is implemented in the NonfairSync
class of ReentrantLock
1 | final void lock() { |
lock()
will first determine whether the lock is idle by compareAndSet(0, 1)
. If it is, the current thread directly acquires the lock. Otherwise, it calls acquire(1)
to acquire the lock.
compareAndSetState()
is aCAS
function. Its role is to compare and set the current lock state. If the lock state value is0
, set the lock state value to1
.- The role of
setExclusiveOwnerThread(Thread.currentThread())
is to set current thread as the holder of lock.
Comparison of lock()
between fair lock and unfair lock
Fair lock
- thelock()
function of fair lock directly callsacquire(1)
.Unfair locks
- Unfair locks first determine whether the current lock status is idle, and if so, they do not queue and acquire the lock directly.
2. acquire()
acquire()
is implemented in AQS
1 | public final void acquire(int arg) { |
- Current thread first tries to acquire the lock through
tryAcquire()
. If the acquisition is successful, return directly. If the attempt fails, enter the waiting queue and sort in sequence, and then acquire the lock. - If the current thread attempt fails, the current thread will be added to the end of the
CLH
queue (non-blocking FIFO queue) throughaddWaiter(Node.EXCLUSIVE)
. - Then, call
acquireQueued()
to acquire the lock. InacquireQueued()
, the current thread will wait for all threads in theCLH
queue to execute and release the lock before it can acquire the lock and return. If the current thread was interrupted during the sleep waiting process, callselfInterrupt()
to generate an interrupt by itself.
Comparison of acquire()
between fair lock and unfair lock
Fair locks and unfair locks differ only in the implementation of the tryAcquire()
function. That is, they have different mechanisms for trying to acquire locks.
The tryAcquire()
of the unfair lock is implemented in the NonfairSync
class of ReentrantLock
1 | protected final boolean tryAcquire(int acquires) { |
nonfairTryAcquire()
is implemented in the Sync
class of ReentrantLock
1 | final boolean nonfairTryAcquire(int acquires) { |
The role of tryAcquire()
is to try to acquire the lock.
- If the lock is not owned by any thread, set the state of the lock through the
CAS
function, and at the same time, set the current thread as the lock holder, and then return true. - If the holder of the lock is already the current thread, the status of the lock will be updated.
- If the above two cases are not used, the attempt is considered to have failed.
Comparison of tryAcquire()
between fair lock and unfair lock
Fair locks and unfair locks have different ways of trying to acquire locks.
When fair lock
tries to acquire the lock, even if the lock is not held by any thread, it will determine whether it is the head of the CLH
waiting queue. If it is, it will acquire the lock.
When unfair lock
tries to acquire a lock, if the lock is not held by any thread, it will directly acquire the lock no matter where it is in the CLH queue.
Release unfair lock (based on JDK 11.0.5)
Unfair locks and fair locks have the same method and strategy for releasing locks.
The release mechanism has been introduced in Java-Multithreading-17-Fair-lock-Release, so I will not repeat here.
Summary
The difference between fair lock and unfair lock is the difference in the mechanism of acquiring a lock.
When trying to acquire a lock
Fair lock
: the lock is only acquired when the current thread is the head of theCLH
waiting queueUnfair lock
: as long as the current lock is idle, the lock is directly acquired, regardless ofCLH
Wait for the order in the queue. Only when the unfair lock attempts to acquire the lock fails, it will enter theCLH
waiting queue and sort like the fair lock.