<link rel="stylesheet" href="https://js.how234.com/third-party/SyntaxHighlighter/shCoreDefault.css" type="text/css" /><script type="text/javascript" src="https://js.how234.com/third-party/SyntaxHighlighter/shCore.js"></script><script type="text/javascript"> SyntaxHighlighter.all(); </script>
java reentrantlock是什麼?一起來看下吧:
是一個可重入且獨佔式的鎖,它具有與使用synchronized監視器鎖相同的基本行為和語義,但與synchronized關鍵字相比,它更靈活、更強大,增加了輪詢、超時、中斷等高階功能。ReentrantLock,顧名思義,它是支援可重入鎖的鎖,是一種遞迴無阻塞的同步機制。除此之外,該鎖還支援獲取鎖時的公平和非公平選擇。
ReentrantLock的內部類Sync繼承了AQS,分為公平鎖FairSync和非公平鎖NonfairSync。如果在絕對時間上,先對鎖進行獲取的請求你一定先被滿足,那麼這個鎖是公平的,反之,是不公平的。公平鎖的獲取,也就是等待時間最長的執行緒最優先獲取鎖,也可以說鎖獲取是順序的。ReentrantLock的公平與否,可以通過它的建構函式來決定。
事實上,公平鎖往往沒有非公平鎖的效率高,但是,並不是任何場景都是以TPS作為唯一指標,公平鎖能夠減少“飢餓”發生的概率,等待越久的請求越能夠得到優先滿足。
ReentrantLock是通過自定義同步器來實現鎖的獲取與釋放,我們以非公平鎖(預設)實現為例,對鎖的獲取和釋放進行詳解。
獲取鎖:
public ReentrantLock() { sync = new NonfairSync();}
即內部同步元件為非公平鎖,獲取鎖的程式碼為:
public void lock() { sync.lock();}
釋放鎖:
成功獲取鎖的執行緒在完成業務邏輯之後,需要呼叫unlock()來釋放鎖:
public void unlock() { sync.release(1);}
unlock()呼叫NonfairSync類的release(int)方法釋放鎖,release(int)方法是定義在AQS中的方法:
public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false;}
tryRelease(int)是子類需要實現的方法:
protected final boolean tryRelease(int releases) { // 計算新的狀態值 int c = getState() - releases; // 判斷當前執行緒是否是持有鎖的執行緒,如果不是的話,丟擲異常 if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; // 新的狀態值是否為0,若為0,則表示該鎖已經完全釋放了,其他執行緒可以獲取同步狀態了 if (c == 0) { free = true; setExclusiveOwnerThread(null); } // 更新狀態值 setState(c); return free;}
如果該鎖被獲取n次,那麼前(n-1)次tryRelease(int)方法必須返回false,只有同步狀態完全釋放了,才能返回true。可以看到,該方法將同步狀態是否為0作為最終釋放的條件,當狀態為0時,將佔有執行緒設為null,並返回true,表示釋放成功。