您好,登錄后才能下訂單哦!
這篇文章主要介紹了ReentrantLock源碼的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
鎖是用來控制多個線程訪問共享資源的方式,一個鎖能夠防止多個線程同時共享資源。
Lock需要顯式的獲取和釋放鎖,擁有了獲取鎖和釋放鎖的可操作性,可中斷的獲取鎖以及超時獲取鎖等多種同步特性
Lock的實(shí)現(xiàn)基本都是通過聚合一個同步器的子類來實(shí)現(xiàn)的。
使用一個int變量來表示同步狀態(tài)
內(nèi)置一個FIFO隊列來完成資源的獲取以及線程的排隊工作
同步器本身未實(shí)現(xiàn)任何同步接口,僅僅是定義了若干同步狀態(tài)獲取和釋放的方法來供自定義同步組件使用
即支持獨(dú)占式獲取同步狀態(tài),也支持共享式獲取同步狀態(tài)
支持一個線程對資源的重復(fù)加鎖
再次獲取鎖:通過判斷當(dāng)前線程是否為獲取鎖的線程來決定獲取操作是否成功,如果是獲取鎖的線程再次請求,則同步狀態(tài)增加并返回成功
鎖的最終釋放:鎖被釋放時,計數(shù)自減,當(dāng)計數(shù)等于0表示鎖已經(jīng)成功釋放
讀寫鎖維護(hù)了一堆鎖,一個讀鎖,一個寫鎖。
通過分離讀鎖和寫鎖,使并發(fā)性相比一般的排它鎖有了很大提升,因為大多數(shù)場景讀多于寫
讀鎖:
支持重進(jìn)入的共享鎖,當(dāng)前線程獲取了寫鎖或者鎖未獲取,當(dāng)前線程增加讀狀態(tài),成功獲取讀鎖
寫鎖:
支持重入的排他鎖,如果存在讀鎖,則寫鎖不能獲取
鎖降級:指的是寫鎖降級為讀鎖
當(dāng)需要阻塞或者喚醒一個線程的時候,都會使用該工具類來完成相應(yīng)工作
提供類似Object的監(jiān)視器方法,與Lock配合實(shí)現(xiàn)等待.通知模式
依賴Lock對象,獲取一個Condition必須通過Lock的NewCondition()方法
是同步器AbstractQueuedSynchronizer的內(nèi)部類
每個Condition包含一個隊列,該隊列是Condition對象實(shí)現(xiàn)等待.通知功能的關(guān)鍵
調(diào)用await()方法,會使當(dāng)前線程進(jìn)入等待隊列,并且釋放鎖,同時線程變成等待狀態(tài)
調(diào)用signal()方法,將會喚醒在隊列中等待時間最長的節(jié)點(diǎn)
public interface Lock { // 省略大部分代碼 /** * Condition 跟Lock綁定 */ Condition newCondition(); } // 通過實(shí)現(xiàn)Lock定義的接口,以及聚合一個隊列同步器AbstractQueuedSynchronizer實(shí)現(xiàn) public class ReentrantLock implements Lock, java.io.Serializable { private static final long serialVersionUID = 7373984872572414699L; /** Synchronizer providing all implementation mechanics */ private final Sync sync; /** * 定義一個內(nèi)部類,繼承同步器 */ abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = -5179523762034025860L; } } /** * 無參數(shù)構(gòu)造方法,默認(rèn)是非公平鎖 */ public ReentrantLock() { sync = new NonfairSync(); } /** * 有參數(shù)構(gòu)造方法,參數(shù)傳遞true,則為公平鎖 */ public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); } // 獲取Condition是通過Lock內(nèi)部的方法在調(diào)用了同步器內(nèi)部的方法實(shí)現(xiàn)的 public Condition newCondition() { return sync.newCondition(); } public class ReentrantLock implements Lock, java.io.Serializable { private static final long serialVersionUID = 7373984872572414699L; /** Synchronizer providing all implementation mechanics */ private final Sync sync; /** * ...... */ abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = -5179523762034025860L; // ...... // 獲取Condition對象,是同步器的內(nèi)部類 final ConditionObject newCondition() { return new ConditionObject(); } // ...... } } // 當(dāng)鎖可用,并且當(dāng)前線程沒有持有該鎖,直接獲取鎖并把count set為1. // 當(dāng)鎖可用,并且當(dāng)前線程已經(jīng)持有該鎖,直接獲取鎖并把count增加1. // 當(dāng)鎖不可用,那么當(dāng)前線程被阻塞,休眠一直到該鎖可以獲取,然后把持有count設(shè)置為1. public void lock() { sync.lock(); } /** * 非公平鎖加鎖 */ static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; /** * Performs lock. Try immediate barge, backing up to normal * acquire on failure. */ final void lock() { if (compareAndSetState(0, 1)) // 設(shè)置當(dāng)前線程 setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } } // 標(biāo)識位進(jìn)行交換 protected final boolean compareAndSetState(int expect, int update) { // See below for intrinsics setup to support this return unsafe.compareAndSwapInt(this, stateOffset, expect, update); } public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); } /** *添加進(jìn)等待隊列 */ final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = false; for (;;) { final Node p = node.predecessor(); if (p == head && tryAcquire(arg)) { setHead(node); p.next = null; // help GC failed = false; return interrupted; } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); } } /** * Convenience method to interrupt current thread. */ static void selfInterrupt() { Thread.currentThread().interrupt(); } /** * 公平鎖 */ static final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L; final void lock() { acquire(1); } /** * Fair version of tryAcquire. Don't grant access unless * recursive call or no waiters or is first. */ protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } } /* * 等待隊列是空,或者當(dāng)前頭節(jié)點(diǎn)就是當(dāng)前線程 */ public final boolean hasQueuedPredecessors() { // The correctness of this depends on head being initialized // before tail and on head.next being accurate if the current // thread is first in queue. Node t = tail; // Read fields in reverse initialization order Node h = head; Node s; return h != t && ((s = h.next) == null || s.thread != Thread.currentThread()); } // 當(dāng)鎖可用,并且當(dāng)前線程沒有持有該鎖,直接獲取鎖并把count set為1. // 當(dāng)鎖可用,并且當(dāng)前線程已經(jīng)持有該鎖,直接獲取鎖并把count增加1. // 獲取鎖時,如果其他線程持有該鎖,無可用鎖資源,直接返回false,這時候線程不用阻塞等待,可以先去做其他事情 public boolean tryLock() { return sync.nonfairTryAcquire(1); } //當(dāng)獲取鎖時,鎖資源在超時時間之內(nèi)變?yōu)榭捎茫⑶以诘却龝r沒有被中斷,那么當(dāng)前線程成功獲取鎖,返回true,同時當(dāng)前線程持有鎖的count設(shè)置為1. // 當(dāng)獲取鎖時,在超時時間之內(nèi)沒有鎖資源可用,那么當(dāng)前線程獲取失敗,不再繼續(xù)等待,返回false. // 當(dāng)獲取鎖時,在超時等待時間之內(nèi),被中斷了,那么拋出InterruptedException,不再繼續(xù)等待. // 當(dāng)獲取鎖時,在超時時間之內(nèi)鎖可用,并且當(dāng)前線程之前已持有該鎖,那么成功獲取鎖,同時持有count加1. public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); } // 釋放鎖 public void unlock() { sync.release(1); } /** * 釋放鎖方法 */ AbstractQueuedSynchronizer.java 的方法 public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; } // ReentrantLock.java的內(nèi)部類Sync的方法 protected final boolean tryRelease(int releases) { int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; }
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“ReentrantLock源碼的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。