ReentrantLock (ReentrantLock) ReentrantLock (ReentrantLock) ReentrantLock (ReentrantLock) ReentrantLock (ReentrantLock
java.util.concurrent.locks.Lock#lock
java.util.concurrent.locks.Lock#lockInterruptibly
java.util.concurrent.locks.Lock#tryLock()
java.util.concurrent.locks.Lock#tryLock(long, java.util.concurrent.TimeUnit)
java.util.concurrent.locks.Lock#unlock
java.util.concurrent.locks.Lock#newCondition
Copy the code
Let’s look at the ReentrantLock constructors. There are only two
private final Sync sync; / / extends AbstractQueuedSynchornizer public already () {/ / no structure, the default is a fair lock sync = new NonfairSync (); } public ReentrantLock(Boolean fair) {sync = fair? new FairSync() : new NonfairSync(); }Copy the code
Once you’ve created the object, you can use it
public void lock() { sync.lock(); } / / directly see the realization of a fair lock Java. Util. Concurrent. The locks. Already. NonfairSync# lock final void the lock () {if (compareAndSetState (0, SetExclusiveOwnerThread (thread.currentThread ())); // Set the thread that owns the lock else acquire(1); } public final void acquire(int arg) {if (! tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); // Failed to get lock and failed to queue}Copy the code
Java. Util. Concurrent. The locks. AbstractQueuedSynchronizer# state records the state of the lock, Number of reentrant Java. Util. Concurrent. The locks. AbstractQueuedSynchronizer# tryAcquire is a hook method, Real implementation in Java. Its subclasses util. Concurrent. The locks. Already. NonfairSync# tryAcquire
protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); If (c == 0) {if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current); return true; } else if (current == getExclusiveOwnerThread()) {int nexTC = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); Return true; } return false; }Copy the code
AcquireQueued (addWaiter(node.exclusive), arg) acquireQueued(addWaiter(Node.exclusive), arg)
private Node addWaiter(Node mode) { Node node = new Node(Thread.currentThread(), mode); // Try the fast path of enq; backup to full enq on failure Node pred = tail; if (pred ! = null) {// There is a value in the queue, add the new node to the end node.prev = pred; if (compareAndSetTail(pred, node)) { pred.next = node; return node; } } enq(node); // Create a return node; } private Node enq(final Node node) { for (;;) { Node t = tail; If (t == null) {// Must initialize if (compareAndSetHead(new Node())); } else {// join the end of the queue node.prev = t; If (compareAndSetTail(t, node)) {t.ext = node; return t; }}}}Copy the code
java.util.concurrent.locks.AbstractQueuedSynchronizer#acquireQueued
final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = false; for (;;) { final Node p = node.predecessor(); If (p == head && tryAcquire(arg)) {// If (p == head && tryAcquire(arg)) { P.ext = null; // help GC failed = false; return interrupted; } the if (shouldParkAfterFailedAcquire (p, node) && parkAndCheckInterrupt ()) / / park interrupted the current thread = true; } } finally { if (failed) cancelAcquire(node); }}Copy the code
So that’s the process of acquiring a lock. If you don’t acquire the lock, the thread will block. Now let’s look at the process of unlocking
public void unlock() { sync.release(1); } public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h ! = null && h.waitStatus ! = 0) unparkSuccessor(h); // Wake up the waiting thread return true; } return false; } protected final boolean tryRelease(int releases) { int c = getState() - releases; If (thread.currentThread ()! = getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; If (c == 0) {// Free = true; setExclusiveOwnerThread(null); } setState(c); return free; } private void unparkSuccessor(Node node) { /* * If status is negative (i.e., possibly needing signal) try * to clear in anticipation of signalling. It is OK if this * fails or if status is changed by waiting thread. */ int ws = node.waitStatus; if (ws < 0) compareAndSetWaitStatus(node, ws, 0); /* * Thread to unpark is held in successor, which is normally * just the next node. But if cancelled or apparently null, * traverse backwards from tail to find the actual * non-cancelled successor. */ Node s = node.next; if (s == null || s.waitStatus > 0) { s = null; for (Node t = tail; t ! = null && t ! = node; t = t.prev) if (t.waitStatus <= 0) s = t; } if (s ! = null) LockSupport.unpark(s.thread); // Wake up the thread}Copy the code
Condition, I’ll see you next time