@@ -104,7 +104,7 @@ ReentrantLock 分为**公平锁**和**非公平锁**,可以通过构造方法
104
104
105
105
106
106
#### 写入队列
107
- 如果 ` tryAcquire(arg) ` 获取锁失败,则需要用 ` acquireQueued( addWaiter(Node.EXCLUSIVE), arg )` 将当前线程写入队列中。
107
+ 如果 ` tryAcquire(arg) ` 获取锁失败,则需要用 ` addWaiter(Node.EXCLUSIVE) ` 将当前线程写入队列中。
108
108
109
109
写入之前需要将当前线程包装为一个 ` Node ` 对象(` addWaiter(Node.EXCLUSIVE) ` )。
110
110
@@ -153,6 +153,76 @@ ReentrantLock 分为**公平锁**和**非公平锁**,可以通过构造方法
153
153
154
154
这个处理逻辑就相当于自旋加上 ` CAS ` 保证一定写入队列。
155
155
156
+ #### 挂起等待线程
157
+
158
+ 写入队列之后需要将当前线程挂起(利用` acquireQueued(addWaiter(Node.EXCLUSIVE), arg) ` ):
159
+
160
+ ``` java
161
+ final boolean acquireQueued(final Node node, int arg) {
162
+ boolean failed = true ;
163
+ try {
164
+ boolean interrupted = false ;
165
+ for (;;) {
166
+ final Node p = node. predecessor();
167
+ if (p == head && tryAcquire(arg)) {
168
+ setHead(node);
169
+ p. next = null ; // help GC
170
+ failed = false ;
171
+ return interrupted;
172
+ }
173
+ if (shouldParkAfterFailedAcquire(p, node) &&
174
+ parkAndCheckInterrupt())
175
+ interrupted = true ;
176
+ }
177
+ } finally {
178
+ if (failed)
179
+ cancelAcquire(node);
180
+ }
181
+ }
182
+ ```
183
+
184
+ 首先会根据 ` node.predecessor() ` 获取到上一个节点是否为头节点,如果是则尝试获取一次锁。
185
+
186
+ 如果不是头节点,或者获取锁失败,则会根据上一个节点的 ` waitStatus ` 来处理(` shouldParkAfterFailedAcquire(p, node) ` )。
187
+
188
+ ` waitStatus ` 用于记录当前节点的状态,如节点取消、节点等待等。
189
+
190
+ ` shouldParkAfterFailedAcquire(p, node) ` 返回当前线程是否需要挂起,如果需要则调用 ` parkAndCheckInterrupt() ` :
191
+
192
+ ``` java
193
+ private final boolean parkAndCheckInterrupt() {
194
+ LockSupport . park(this );
195
+ return Thread . interrupted();
196
+ }
197
+ ```
198
+
199
+ 他是利用 ` LockSupport ` 的 ` part ` 方法来挂起当前线程的,直到被唤醒。
200
+
201
+
202
+ ### 非公平锁获取锁
203
+ 公平锁与非公平锁的差异主要在获取锁:
204
+
205
+ 公平锁就相当于买票,后来的人需要排到队尾依次买票,不能插队。
206
+
207
+ 而非公平锁则没有这些规则,是** 抢占模式** ,每来一个人不会去管队列如何,直接尝试获取锁。
208
+
209
+ 非公平锁:
210
+ ``` java
211
+ final void lock() {
212
+ // 直接尝试获取锁
213
+ if (compareAndSetState(0 , 1 ))
214
+ setExclusiveOwnerThread(Thread . currentThread());
215
+ else
216
+ acquire(1 );
217
+ }
218
+ ```
219
+
220
+ 公平锁:
221
+ ``` java
222
+ final void lock() {
223
+ acquire(1 );
224
+ }
225
+ ```
226
+
156
227
157
228
158
-
0 commit comments