@@ -104,7 +104,7 @@ ReentrantLock 分为**公平锁**和**非公平锁**,可以通过构造方法
104104
105105
106106#### 写入队列
107- 如果 ` tryAcquire(arg) ` 获取锁失败,则需要用 ` acquireQueued( addWaiter(Node.EXCLUSIVE), arg )` 将当前线程写入队列中。
107+ 如果 ` tryAcquire(arg) ` 获取锁失败,则需要用 ` addWaiter(Node.EXCLUSIVE) ` 将当前线程写入队列中。
108108
109109写入之前需要将当前线程包装为一个 ` Node ` 对象(` addWaiter(Node.EXCLUSIVE) ` )。
110110
@@ -153,6 +153,76 @@ ReentrantLock 分为**公平锁**和**非公平锁**,可以通过构造方法
153153
154154这个处理逻辑就相当于自旋加上 ` CAS ` 保证一定写入队列。
155155
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+
156227
157228
158-
0 commit comments