Welcome to github.com/hsfxuebao/j… , hope to help you, if you feel ok, please click on the Star

From: blog.csdn.net/qq\_4332709…

ReentrantLock: ReentrantLock: ReentrantLock: ReentrantLock: ReentrantLock: ReentrantLock

ReentrantLock Unlocking resolution

Let’s start with an application that performs the underlying source code analysis step by step from unlock().

0. Write a Demo first
	public static void main(String[] args) {
	   final ReentrantLock reentrantLock = new ReentrantLock(true);
	    Thread t1 = new Thread(() -> {
	        reentrantLock.lock();
	        sleep(2000);
	        reentrantLock.unlock();
	    });
	    t1.start();
	}
123456789
Copy the code
1. First call template method sync.release(1)

Since fair locks are unlocked in the same way as non-fair locks, both reentrantLocks call sync.release(1).

public void unlock() {
        sync.release(1);
    }
123
Copy the code
2. Template method Release (1) analysis
Public final Boolean release(int arg) {// If (tryRelease(arg)) {Node h = head; // If the queue head is not empty and the subsequent thread is in some state, then the first queued thread is woken up. = null && h.waitStatus ! = 0) unparkSuccessor(h); return true; } return false; } 1234567891011Copy the code
3. TryRelease (ARG) attempted to analyze the unlocking method
Protected final Boolean tryRelease(int releases) {// Get the lock state-1 and then determine whether it is free (c=0?). Int c = getState() -releases the lock again; If (thread.currentThread ()! = getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; If (c == 0) {free = true; setExclusiveOwnerThread(null); } setState(c); return free; } 123456789101112131415161718Copy the code
4. Analysis of the method of waking up the queue waiting threads (H)

Note: in the previous article, we analyzed that the previous node WS stores the state of the next node thread

Private void unparksucceeded (Node Node) {// the state of the next Node thread ws int ws = node.waitStatus; If (ws < 0) compareAndSetWaitStatus(node, ws, 0); Node s = node.next; / / the queue is only one team head nodes or ws > 0 s thread needs to cancel from the synchronous queue waiting for the if (s = = null | | s. aitStatus > 0) {s = null; For (Node t = tail; for (Node t = tail; for (Node t = tail; t ! = null && t ! = node; t = t.prev) if (t.waitStatus <= 0) s = t; } // If this node is not null, wake it up. = null) LockSupport.unpark(s.thread); } 123456789101112131415161718192021Copy the code

Normally the next thread of the queue head is awakened, but if the thread is in the ws=1 state, it starts at the end of the queue and finds the nearest normal thread to the queue head. (ws<=0 thread) (ws<=0 thread)

Question: since s=null in the judgment directly return not line, why still enter the loop to find the node? If the unparksucceeded () method can be called, the thread holding the lock has been successfully unlocked. Then there are no elements in the queue when s == null of the unparksucceeded () method, but since it is multithreaded, It is possible that after entering the if block, multiple threads attempt to lock, at which point the queue element will increase, even if s= NULL at the time of determination, but there is no guarantee that s= NULL at the next time, so it is necessary to enter the following loop. 1234567Copy the code

The flow chart of unlock ()



Reference:

1. The Art of Concurrent Programming in Java

2,JUC AQS ReentrantLock

3,ReentrantLock implementation principle analysis