Skip to content

Commit 0bbfbfe

Browse files
committed
📝 Writing docs.
1 parent 101f6d6 commit 0bbfbfe

File tree

1 file changed

+98
-9
lines changed

1 file changed

+98
-9
lines changed

docs/concurrent/Java锁.md

Lines changed: 98 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ tags:
3131
- [ReentrantReadWriteLock](#reentrantreadwritelock)
3232
- [要点](#要点-3)
3333
- [示例](#示例-1)
34+
- [AQS](#aqs)
35+
- [要点](#要点-4)
36+
- [源码](#源码-3)
37+
- [独占锁](#独占锁)
3438
- [资料](#资料)
3539

3640
<!-- /TOC -->
@@ -177,13 +181,15 @@ public class ReentrantLockDemo {
177181

178182
### 要点
179183

180-
* 功能
181-
* 对于特定的资源,ReadWriteLock 允许多个线程同时对其执行读操作,但是只允许一个线程对其执行写操作。
182-
* 原理
183-
* “读-读”线程之间不存在互斥关系。
184-
* “读-写”线程、“写-写”线程之间存在互斥关系。
185-
* ReadWriteLock 维护一对相关的锁。一个是读锁;一个是写锁。
186-
* 将读写锁分开,有利于提高并发效率。
184+
作用:对于特定的资源,ReadWriteLock 允许多个线程同时对其执行读操作,但是只允许一个线程对其执行写操作。
185+
186+
原理
187+
188+
“读-读”线程之间不存在互斥关系。
189+
190+
“读-写”线程、“写-写”线程之间存在互斥关系。
191+
192+
ReadWriteLock 维护一对相关的锁。一个是读锁;一个是写锁。将读写锁分开,有利于提高并发效率。
187193

188194
<p align="center">
189195
<img src="https://raw.githubusercontent.com/dunwu/javase-notes/master/images/concurrent/ReadWriteLock.jpg">
@@ -211,8 +217,7 @@ public interface ReadWriteLock {
211217

212218
### 要点
213219

214-
* 功能
215-
* ReentrantReadWriteLock 实现了 ReadWriteLock 接口,所以它是一个读写锁。
220+
作用:ReentrantReadWriteLock 实现了 ReadWriteLock 接口,所以它是一个读写锁。
216221

217222
### 示例
218223

@@ -243,8 +248,92 @@ public class ReentrantReadWriteLockDemo {
243248
}
244249
```
245250

251+
## AQS
252+
253+
### 要点
254+
255+
作用:AQS,AbstractQueuedSynchronizer,即队列同步器。它是构建锁或者其他同步组件的基础框架(如 ReentrantLock、ReentrantReadWriteLock、Semaphore 等)。
256+
257+
场景:在 LOCK 包中的相关锁(常用的有 ReentrantLock、 ReadWriteLock)都是基于 AQS 来构建。然而这些锁都没有直接来继承 AQS,而是定义了一个 Sync 类去继承 AQS。那么为什么要这样呢?because:锁面向的是使用用户,而同步器面向的则是线程控制,那么在锁的实现中聚合同步器而不是直接继承 AQS 就可以很好的隔离二者所关注的事情。
258+
259+
原理:AQS 在内部定义了一个 int 变量 state,用来表示同步状态。AQS 通过一个双向的 FIFO 同步队列来完成同步状态的管理,当有线程获取锁失败后,就被添加到队列末尾。
260+
261+
### 源码
262+
263+
AbstractQueuedSynchronizer 继承自 AbstractOwnableSynchronize。
264+
265+
#### 同步队列
266+
267+
```java
268+
public abstract class AbstractQueuedSynchronizer
269+
extends AbstractOwnableSynchronizer
270+
implements java.io.Serializable {
271+
272+
/** 等待队列的队头,懒加载。只能通过 setHead 方法修改。 */
273+
private transient volatile Node head;
274+
/** 等待队列的队尾,懒加载。只能通过 enq 方法添加新的等待节点。*/
275+
private transient volatile Node tail;
276+
/** 同步状态 */
277+
private volatile int state;
278+
}
279+
```
280+
281+
<p align="center">
282+
<img src="http://www.liuhaihua.cn/wp-content/uploads/2018/05/7zei6fI.png">
283+
</p>
284+
285+
##### Node
286+
287+
```java
288+
static final class Node {
289+
/** 该等待同步的节点处于共享模式 */
290+
static final Node SHARED = new Node();
291+
/** 该等待同步的节点处于独占模式 */
292+
static final Node EXCLUSIVE = null;
293+
294+
/** 等待状态,这个和 state 是不一样的:有 1,0,-1,-2,-3 五个值 */
295+
volatile int waitStatus;
296+
static final int CANCELLED = 1;
297+
static final int SIGNAL = -1;
298+
static final int CONDITION = -2;
299+
static final int PROPAGATE = -3;
300+
301+
/** 前驱节点 */
302+
volatile Node prev;
303+
/** 后继节点 */
304+
volatile Node next;
305+
/** 等待锁的线程 */
306+
volatile Thread thread;
307+
}
308+
```
309+
310+
很显然,Node 是一个双链表结构。
311+
312+
waitStatus 5 个状态值的含义:
313+
314+
1. CANCELLED(1) - 该节点的线程可能由于超时或被中断而处于被取消(作废)状态,一旦处于这个状态,节点状态将一直处于 CANCELLED(作废),因此应该从队列中移除.
315+
2. SIGNAL(-1) - 当前节点为 SIGNAL 时,后继节点会被挂起,因此在当前节点释放锁或被取消之后必须被唤醒(unparking)其后继结点.
316+
3. CONDITION(-2) - 该节点的线程处于等待条件状态,不会被当作是同步队列上的节点,直到被唤醒(signal),设置其值为 0,重新进入阻塞状态。
317+
4. PROPAGATE(-3) - 下一个 acquireShared 应无条件传播。
318+
5. 0 - 非以上状态。
319+
320+
```java
321+
public final void acquire(int arg) {
322+
if (!tryAcquire(arg) &&
323+
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
324+
selfInterrupt();
325+
}
326+
```
327+
328+
### 独占锁
329+
330+
独占锁的获取(acquire方法)
331+
246332
## 资料
247333

248334
* [Java 并发编程实战](https://item.jd.com/10922250.html)
249335
* [Java 并发编程的艺术](https://item.jd.com/11740734.html)
250336
* http://www.cnblogs.com/dolphin0520/p/3923167.html
337+
* https://zhuanlan.zhihu.com/p/27134110
338+
* https://t.hao0.me/java/2016/04/01/aqs.html
339+
* http://ju.outofmemory.cn/entry/353762

0 commit comments

Comments
 (0)