File tree Expand file tree Collapse file tree 1 file changed +66
-1
lines changed
Expand file tree Collapse file tree 1 file changed +66
-1
lines changed Original file line number Diff line number Diff line change 44
55而 ` ReentrantLock ` 就是一个普通的类,它是基于 ` AQS(AbstractQueuedSynchronizer) ` 来实现的。
66
7+ 它是一个** 重入锁** ,一个线程获得了锁之后仍然可以** 反复** 的加锁,不会出现自己阻塞自己的情况。
8+
79> ` AQS ` 是 ` Java ` 并发包里实现锁、同步的一个基础框架。
810
911
@@ -90,4 +92,67 @@ ReentrantLock 分为**公平锁**和**非公平锁**,可以通过构造方法
9092 return false ;
9193 }
9294 }
93- ```
95+ ```
96+
97+ 首先会判断 ` AQS ` 中的 ` state ` 是否等于0,0 就表示当前没有其他线程获得锁,当前线程就可以尝试获取锁。
98+
99+ 注意:尝试之前会利用 ` hasQueuedPredecessors() ` 方法来判断 AQS 的队列中中是否有其他线程,如果有则就不会尝试获取锁了(** 这是公平锁特有的情况** )。
100+
101+ 如果队列中没有线程就利用 CAS 来将 AQS 中的 state 修改为1,也就是获取锁,获取成功则将当前线程置为获得锁的独占线程(` setExclusiveOwnerThread(current) ` )。
102+
103+ 如果 ` state ` 大于 0 时,说明锁已经被获取了,则需要判断获取锁的线程是否为当前线程(` ReentrantLock ` 支持重入),是则需要将 ` state + 1 ` ,并将值更新。
104+
105+
106+ #### 写入队列
107+ 如果 ` tryAcquire(arg) ` 获取锁失败,则需要用 ` acquireQueued(addWaiter(Node.EXCLUSIVE), arg) ` 将当前线程写入队列中。
108+
109+ 写入之前需要将当前线程包装为一个 ` Node ` 对象(` addWaiter(Node.EXCLUSIVE) ` )。
110+
111+ > AQS 中的队列是由 Node 节点组成的双向链表实现的。
112+
113+
114+ 包装代码:
115+
116+ ``` java
117+ private Node addWaiter(Node mode) {
118+ Node node = new Node (Thread . currentThread(), mode);
119+ // Try the fast path of enq; backup to full enq on failure
120+ Node pred = tail;
121+ if (pred != null ) {
122+ node. prev = pred;
123+ if (compareAndSetTail(pred, node)) {
124+ pred. next = node;
125+ return node;
126+ }
127+ }
128+ enq(node);
129+ return node;
130+ }
131+
132+ ```
133+
134+ 首先判断队列是否为空,不为空时则将封装好的 ` Node ` 利用 ` CAS ` 写入队尾,如果出现并发写入失败就需要调用 ` enq(node); ` 来写入了。
135+
136+ ``` java
137+ private Node enq(final Node node) {
138+ for (;;) {
139+ Node t = tail;
140+ if (t == null ) { // Must initialize
141+ if (compareAndSetHead(new Node ()))
142+ tail = head;
143+ } else {
144+ node. prev = t;
145+ if (compareAndSetTail(t, node)) {
146+ t. next = node;
147+ return t;
148+ }
149+ }
150+ }
151+ }
152+ ```
153+
154+ 这个处理逻辑就相当于自旋加上 ` CAS ` 保证一定写入队列。
155+
156+
157+
158+
You can’t perform that action at this time.
0 commit comments