Master ReentrantLock
Specific structure
Reentrantlock is referred to as RL below. It is strongly recommended to read the AQS source code analysis before reading:/seamount3/p/18690818
In fact, RL is related to AQS, but not directly. There is a Sync variable inside RL. RL actually implements the LOCK interface to implement the corresponding LOCK method.
What is SYNC, which is actually an internal class Extends AQS, and there are two subclasses inside a fair lock and non -fair lock
The core of RL is on the subclass of the corresponding internal class Sync
Subclass FairSync
lock
final void lock() {
acquire(1);
}
It's not too much to say, in fact, it's just packaging, call the AQS access method of AQS
What is relatively interesting is why 1?
1 is actually a parameter abstracted by AQS. Here it represents the number of permissions that a thread needs to obtain when requesting a lock.
Here1
Represents the current thread requestoneThe lock permit, the operation of the lock is based on permission.
Look at the following TRYACQUIRE
tryAcquire
protected final boolean tryAcquire(int acquires) {
final Thread current = ();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
Relatively simple, the process is as follows:
- Get the current state variable
- state=0, determine whether CLH has nodes
- If not, then perform CAS operation state
- If the operation is successful, set it to an exclusive thread
- state=0, determine whether CLH has nodes
- In order to achieve recurrence, then consider whether the exclusive thread is the current thread
- If yes, int nextC = C + Acquires; and setState
Subclass NonfairSync
lock
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(());
else
acquire(1);
}
tryAcquire
No need to go into details
What functions does the Sync parent class implement?
Core TryRelease
The implementation of this method is to implement the corresponding hook method for AQS. The unlock method of RL will eventually call the release of AQS.
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
The core process is as follows:
- Determine whether the current thread is a thread held by lock resources
- If not, throw an exception
- After 1OK, modify the state
- If the state is changed == 0, then the lock is completely released
- If it does not mean just modifying the state, the lock is not released, in order to support it, it can be re -entered.
How can the interviewer introduce the introduction of ReentrantLock?
- Quick and brief introduction (including function)
- How to achieve it in detail
Quick and simple introduction (including functions)
First, ReentrantLock implements the corresponding Lock interface. Its function basically functions as a local lock.
ReentrantLock functionally supports:
- Mutual exclusivity (RL is a mutex lock. Only one thread is allowed to acquire the lock and enter the critical section at the same time. Write operations are naturally mutually exclusive.)
- Repeatability
- fair and unfair
- Interruptible,
lockInterruptibly()
Methods, allowing threads to be interrupted during the waiting process of waiting lock - Time limit, for example, TryLock allows a thread to try to acquire the lock within a specified time. If the lock is not acquired within the specified time, the thread will return
false
。
Most of the above functions are using the existing code of AQS, as well as internal internal classes such as FAIRSYNC inheritance of AQS and implementing corresponding hook methods such as Tryacquire to achieve overall functions
How to achieve it in detail
Let’s talk about the lock process:
- First of all, the entrance is the LOCK method of the RL, and the bottom layer is actually the access method of the internal variable Sync (that is, the Acquire template method of AQS)
- This reflects the difference between fairness and non-public. In the constructor, we will generate an instance of a fair lock or an instance of an unfair lock. Through this, fairness and unfairness are realized.
- Take fairness as an example, then we will perform the AQS access process
- First call tryAcquire corresponding to the fair lock implementation
- Get the current state variable
- state=0, determine whether CLH has nodes
- If not, then perform CAS operation state
- If the operation is successful, set it to the exclusive thread
- state=0, determine whether CLH has nodes
- In order to achieve reentrancy, you must also consider whether the exclusive thread is the current thread.
- If yes, int nextc = c + acquires; and setState
- Get the current state variable
- First call tryAcquire corresponding to the fair lock implementation
- If TRYACQUIRE fails, then enter the current thread to add to Node to the end process of the CLH team, and then wait to wake up. Then there is an important way to correspond to it, which is an ACQUIREQUEUED, which is equivalent to a dead cycle. Obstruct, wait for wake -up later
Talk about the Unlock process:
- The Release method corresponding to the SYNC class will be called inside (that is, the template method implemented by AQS)
- Then execute the corresponding tryRelease process
- Finally awaken the next node in the queue
The interruptible function just mentioned is also supported by AQS locks, as well as the timeout mechanism. They are all used by AQS in specific codes. For example, the interruptible function will determine the thread status during the loop, while the timeout function will combine the current time and the timeout during the loop process. Find the difference between the starting times to judge