[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/xinrun0928/JavaGuide/main/docs/java/concurrent/reentrantlock.md [Back]  [Original]

---
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 

![img](https://p0.meituan.net/travelcube/412d294ff5535bbcddc0d979b2a339e6102264.png)



```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 

![](https://p1.meituan.net/travelcube/82077ccf14127a87b77cefd1ccf562d3253591.png)

-  Method Attribution
- AQS  AQS  API 
-  API  AQS 

 AQS 

![](https://p1.meituan.net/travelcube/d2f7f7fffdc30d85d17b44266c3ab05323338.png)

### 2.1 

AQS  CLH 

CLHCraigLandin and Hagersten AQS  CLH FIFOAQS 



![](https://p0.meituan.net/travelcube/7132e4cef44c26f62835b197b239147b18062.png)

AQS  Volatile  int  FIFO  CAS  State 

#### 2.1.1 AQS 

 AQS NodeNode  CLH 

![](https://p1.meituan.net/travelcube/960271cf2b5c8a185eed23e98b72c75538637.png)



|  |                                                          |
| :----------- | :----------------------------------------------------------- |
| 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 

![](https://p0.meituan.net/travelcube/27605d483e8935da683a93be015713f331378.png)

![](https://p0.meituan.net/travelcube/3f1e1a44f5b7d77000ba4f9476189b2e32806.png)

 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 

![](https://p1.meituan.net/travelcube/b8b53a70984668bc68653efe9531573e78636.png)

 ReentrantLock  AQS 

![](https://p1.meituan.net/travelcube/7aadb272069d871bdee8bf3a218eed8136919.png)



-  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 

![](https://p0.meituan.net/travelcube/f30c631c8ebbf820d3e8fcb6eee3c0ef18748.png)

## 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 

![img](https://p0.meituan.net/travelcube/e9e385c3c68f62c67c8d62ab0adb613921117.png)

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();
}
```



![](https://p0.meituan.net/travelcube/c124b76dcbefb9bdc778458064703d1135485.png)

 CPU shouldParkAfterFailedAcquire 

![](https://p0.meituan.net/travelcube/9af16e2481ad85f38ca322a225ae737535740.png)



- 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)

Web Proxy Viewer  |  New URL  |  Original Page