File tree Expand file tree Collapse file tree 1 file changed +70
-0
lines changed
Expand file tree Collapse file tree 1 file changed +70
-0
lines changed Original file line number Diff line number Diff line change @@ -224,5 +224,75 @@ ReentrantLock 分为**公平锁**和**非公平锁**,可以通过构造方法
224224 }
225225```
226226
227+ 还要一个重要的区别是在尝试获取锁时` tryAcquire(arg) ` ,非公平锁是不需要判断队列中是否还有其他线程,也是直接尝试获取锁:
228+
229+ ``` java
230+ final boolean nonfairTryAcquire(int acquires) {
231+ final Thread current = Thread . currentThread();
232+ int c = getState();
233+ if (c == 0 ) {
234+ // 没有 !hasQueuedPredecessors() 判断
235+ if (compareAndSetState(0 , acquires)) {
236+ setExclusiveOwnerThread(current);
237+ return true ;
238+ }
239+ }
240+ else if (current == getExclusiveOwnerThread()) {
241+ int nextc = c + acquires;
242+ if (nextc < 0 ) // overflow
243+ throw new Error (" Maximum lock count exceeded" );
244+ setState(nextc);
245+ return true ;
246+ }
247+ return false ;
248+ }
249+ ```
250+
251+ ## 释放锁
252+
253+ 公平锁和非公平锁的释放流程都是一样的:
254+
255+ ``` java
256+ public void unlock() {
257+ sync. release(1 );
258+ }
259+
260+ public final boolean release(int arg) {
261+ if (tryRelease(arg)) {
262+ Node h = head;
263+ if (h != null && h. waitStatus != 0 )
264+ unparkSuccessor(h);
265+ return true ;
266+ }
267+ return false ;
268+ }
269+
270+ // 尝试释放锁
271+ protected final boolean tryRelease(int releases) {
272+ int c = getState() - releases;
273+ if (Thread . currentThread() != getExclusiveOwnerThread())
274+ throw new IllegalMonitorStateException ();
275+ boolean free = false ;
276+ if (c == 0 ) {
277+ free = true ;
278+ setExclusiveOwnerThread(null );
279+ }
280+ setState(c);
281+ return free;
282+ }
283+ ```
284+
285+ 首先会判断当前线程是否为获得锁的线程,由于是重入锁所以需要将 ` state ` 减到 0 才认为完全释放锁。
286+
287+ 释放之后需要调用 ` unparkSuccessor(h) ` 来唤醒被挂起的线程。
288+
289+
290+ ## 总结
291+
292+ 由于公平锁需要关心队列的情况,得按照队列里的先后顺序来获取锁(会造成大量的线程上下文切换),而非公平锁则没有这个逻辑。
293+
294+ 所以也就能解释非公平锁的效率会被公平锁更高。
295+
296+
227297
228298
You can’t perform that action at this time.
0 commit comments