---
title: ReentrantLockAQS
category: Java
tag:
- Java
---
> https://tech.meituan.com/2019/12/05/aqs-theory-and-apply.html
>
>
##
Java SemaphoreReentrantLock AbstractQueuedSynchronizer AQSAQS ReentrantLock ReentrantLock AQS AQS AQS AQS Sync Queue Condition Queue AQS ReentrantLock ReentrantLock
## 1 ReentrantLock
### 1.1 ReentrantLock
ReentrantLock ReentrantLock ReentrantLock Synchronized

```java
// **************************Synchronized**************************
// 1.
synchronized (this) {}
// 2.
synchronized (object) {}
// 3.
public synchronized void test () {}
// 4.
for (int i = 0; i < 100; i++) {
synchronized (this) {}
}
// **************************ReentrantLock**************************
public void test () throw Exception {
// 1.
ReentrantLock lock = new ReentrantLock(true);
// 2.
lock.lock();
try {
try {
// 3.;
if(lock.tryLock(100, TimeUnit.MILLISECONDS)){ }
} finally {
// 4.
lock.unlock()
}
} finally {
lock.unlock();
}
}
```
### 1.2 ReentrantLock AQS
ReentrantLock [ Java](https://mp.weixin.qq.com/s?__biz=MjM5NjQ5MTI5OA==&mid=2651749434&idx=3&sn=5ffa63ad47fe166f2f1a9f604ed10091&chksm=bd12a5778a652c61509d9e718ab086ff27ad8768586ea9b38c3dcf9e017a8e49bcae3df9bcc8&scene=38#wechat_redirect) ReentrantLock AQS ReentrantLock AQS AQS AQS
```java
// java.util.concurrent.locks.ReentrantLock#NonfairSync
//
static final class NonfairSync extends Sync {
...
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
...
}
```
- CAS State
- CAS State Acquire
-
(1) AQS
(2)
- 1
-
-
```
// java.util.concurrent.locks.ReentrantLock#FairSync
static final class FairSync extends Sync {
...
final void lock() {
acquire(1);
}
...
}
```
Lock Acquire
Acquire Acquire FairSync UnfairSync AQS
ReentrantLock Acquire AbstractQueuedSynchronizer AQS AQS ReentrantLock AQS 2.3.5
## 2 AQS
AQS

- Method Attribution
- AQS AQS API
- API AQS
AQS

### 2.1
AQS CLH
CLHCraigLandin and Hagersten AQS CLH FIFOAQS

AQS Volatile int FIFO CAS State
#### 2.1.1 AQS
AQS NodeNode CLH

| | |
| :----------- | :----------------------------------------------------------- |
| waitStatus | |
| thread | |
| prev | |
| predecessor | npe |
| nextWaiter | CONDITION Condition Queue |
| next | |
| | |
| :-------- | :----------------------------- |
| SHARED | |
| EXCLUSIVE | |
waitStatus
| | |
| :-------- | :----------------------------------------------- |
| 0 | Node |
| CANCELLED | 1 |
| CONDITION | -2 |
| PROPAGATE | -3 SHARED |
| SIGNAL | -1 |
#### 2.1.2 State
AQS StateAQS state Volatile
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
private volatile int state;
```
| | |
| :----------------------------------------------------------- | :---------------------- |
| protected final int getState() | State |
| protected final void setState(int newState) | State |
| protected final boolean compareAndSetState(int expect, int update) | CAS State |
Final State


AQS API
## 2.2 AQS ReentrantLock
AQS Protected State ReentrantLock
| | |
| :------------------------------------------ | :----------------------------------------------------------- |
| protected boolean isHeldExclusively() | Condition |
| protected boolean tryAcquire(int arg) | arg True False |
| protected boolean tryRelease(int arg) | arg True False |
| protected int tryAcquireShared(int arg) | arg 0 |
| protected boolean tryReleaseShared(int arg) | arg True False |
tryAcquire-tryReleasetryAcquireShared-tryReleaseShared AQS ReentrantReadWriteLockReentrantLock tryAcquire-tryRelease
AQS

ReentrantLock AQS

- ReentrantLock Lock
- Sync Lock Sync#lock ReentrantLock Lock AQS Acquire
- AQS Acquire tryAcquire tryAcquire ReentrantLock tryAcquire ReentrantLock tryAcquire tryAcquire
- tryAcquire AQS ReentrantLock
- ReentrantLock Unlock
- Unlock Sync Release AQS
- Release tryRelease tryRelease tryRelease ReentrantLock Sync
- AQS
ReentrantLock API

## 2.3 ReentrantLock AQS
ReentrantLock
```java
// java.util.concurrent.locks.ReentrantLock
static final class NonfairSync extends Sync {
...
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
...
}
```
Acquire
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
```
tryAcquire
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
```
AQS ReentrantLock True
### 2.3.1
#### 2.3.1.1
Acquire(1) tryAcquire addWaiter
#### 2.3.1.2
addWaiter(Node.EXCLUSIVE)
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
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) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
private final boolean compareAndSetTail(Node expect, Node update) {
return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
}
```
-
- Pred Tail
- New Node Prev Pred
- compareAndSetTail tailOffset Expect tailOffset Node Expect Node Tail Update
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
static {
try {
stateOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("state"));
headOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("head"));
tailOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
waitStatusOffset = unsafe.objectFieldOffset(Node.class.getDeclaredField("waitStatus"));
nextOffset = unsafe.objectFieldOffset(Node.class.getDeclaredField("next"));
} catch (Exception ex) {
throw new Error(ex);
}
}
```
AQS tailOffset tail new Node
- Pred Null Pred Tail Enq
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
```
addWaiter
1. 1
2. 2 1

1.
hasQueuedPredecessors False True
```java
// java.util.concurrent.locks.ReentrantLock
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t && ((s = h.next) == null || s.thread != Thread.currentThread());
}
```
h != t && ((s = h.next) == null || s.thread != Thread.currentThread());
> h != t (s = h.next) == null Tail Head Head Tail True (s = h.next) != null s.thread == Thread.currentThread() s.thread != Thread.currentThread()
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer#enq
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
```
head != tail Tail Tail Head Head Tail 567
#### 2.3.1.3
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
```
addWaiter Node Node Node acquireQueued acquireQueued
acquireQueued
acquireQueued
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
final boolean acquireQueued(final Node node, int arg) {
//
boolean failed = true;
try {
//
boolean interrupted = false;
//
for (;;) {
//
final Node p = node.predecessor();
// p
if (p == head && tryAcquire(arg)) {
// node
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
// ppnodewaitStatus-1
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
```
setHead waitStatus
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
private void setHead(Node node) {
head = node;
node.thread = null;
node.prev = null;
}
// java.util.concurrent.locks.AbstractQueuedSynchronizer
//
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
//
int ws = pred.waitStatus;
//
if (ws == Node.SIGNAL)
return true;
// waitStatus>0
if (ws > 0) {
do {
//
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
// SIGNAL
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
```
parkAndCheckInterrupt
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
```

CPU shouldParkAfterFailedAcquire

- shouldParkAfterFailedAcquire waitStatus -1
-
### 2.3.2 CANCELLED
acquireQueued Finally
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
...
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
...
failed = false;
...
}
...
} finally {
if (failed)
cancelAcquire(node);
}
}
```
cancelAcquire Node CANCELLED
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
private void cancelAcquire(Node node) {
//
if (node == null)
return;
//
node.thread = null;
Node pred = node.prev;
// node
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
//
Node predNext = pred.next;
// nodeCANCELLED
node.waitStatus = Node.CANCELLED;
//
// elsetailnull
if (node == tail && compareAndSetTail(node, pred)) {
compareAndSetNext(pred, predNext, null);
} else {
int ws;
// head1:SIGNAL2:SINGAL
// 12truenull
//
if (pred != head && ((ws = pred.waitStatus) == Node.SIGNAL || (ws ```java
> do {
> node.prev = pred = pred.prev;
> } while (pred.waitStatus > 0);
> ```
### 2.3.3
ReentrantLock
```java
// java.util.concurrent.locks.ReentrantLock
public void unlock() {
sync.release(1);
}
```
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
```
ReentrantLock Sync
```java
// java.util.concurrent.locks.ReentrantLock.Sync
//
protected final boolean tryRelease(int releases) {
//
int c = getState() - releases;
//
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// nullstate
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
```
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
public final boolean release(int arg) {
// tryReleasetrue
if (tryRelease(arg)) {
//
Node h = head;
// waitStatus
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
```
h != null && h.waitStatus != 0
> h == null Head head == nullHead head == null
>
> h != null && waitStatus == 0
>
> h != null && waitStatus < 0
unparkSuccessor
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
private void unparkSuccessor(Node node) {
// waitStatus
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
//
Node s = node.next;
// nullcancelledcancelled
if (s == null || s.waitStatus > 0) {
s = null;
// waitStatus A
>
> Q
>
> A CLH FIFO
>
> Q
>
> A 2.3.1.3
>
> Q
>
> A 2.3.2
>
> QLock Acquire
>
> AAQS Acquire tryAcquire tryAcquire tryAcquire
## 3 AQS
### 3.1 ReentrantLock
ReentrantLock AQS ReentrantLock ReentrantLock
```java
// java.util.concurrent.locks.ReentrantLock.FairSync#tryAcquire
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;
}
```
```java
// java.util.concurrent.locks.ReentrantLock.Sync#nonfairTryAcquire
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;
}
```
State State Volatile
```java
// java.util.concurrent.locks.AbstractQueuedSynchronizer
private volatile int state;
```
State
1. State 0
2. +1+1
3. -1 0
### 3.2 JUC
ReentrantLock AQS JUC AQS
| | AQS |
| :--------------------- | :----------------------------------------------------------- |
| ReentrantLock | AQS ReentrantLock |
| Semaphore | AQS tryRelease acquireShared |
| CountDownLatch | AQS 0 Acquire CountDownLatch await |
| ReentrantReadWriteLock | AQS 16 16 |
| ThreadPoolExecutor | Worker AQS tryAcquire tryRelease |
### 3.3
AQS AQS
```java
public class LeeLock {
private static class Sync extends AbstractQueuedSynchronizer {
@Override
protected boolean tryAcquire (int arg) {
return compareAndSetState(0, 1);
}
@Override
protected boolean tryRelease (int arg) {
setState(0);
return true;
}
@Override
protected boolean isHeldExclusively () {
return getState() == 1;
}
}
private Sync sync = new Sync();
public void lock () {
sync.acquire(1);
}
public void unlock () {
sync.release(1);
}
}
```
Lock
```java
public class LeeMain {
static int count = 0;
static LeeLock leeLock = new LeeLock();
public static void main (String[] args) throws InterruptedException {
Runnable runnable = new Runnable() {
@Override
public void run () {
try {
leeLock.lock();
for (int i = 0; i < 10000; i++) {
count++;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
leeLock.unlock();
}
}
};
Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnable);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(count);
}
}
```
20000 AQS
##
ReentrantLock AQS AQS ReentrantLock
##
- Lea D. The java. util. concurrent synchronizer framework[J]. Science of Computer Programming, 2005, 58(3): 293-309.
- Java
- [ Java](https://tech.meituan.com/2018/11/15/java-lock.html)