java 手動實現一個可重入鎖
阿新 • • 發佈:2019-02-09
手動實現一個可重入鎖
下面程式碼給出了一個手動實現的可重入鎖,MyLock類,實現了Lock介面,需要編寫的兩個函式為lock()和unlock()。isLocked變數用來判斷當前是否有執行緒使用,若沒有,則為false。lockBy變數儲存了當前持有的執行緒。lockcount變數儲存當前持有的執行緒的計數器。函式中呼叫wait()和notify()時,需要加上關鍵字synchronized。
package com.concur.class21; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; public class MyLock implements Lock{ private boolean isLocked=false; private Thread lockBy=null; private int lockcount=0; @Override public synchronized void lock() { Thread currentThread=Thread.currentThread();//1 while(isLocked&¤tThread!=lockBy)){//2 try { wait();//3 } catch (InterruptedException e) { e.printStackTrace(); } } isLocked=true;//4 lockBy=currentThread;//5 lockcount++;//6 } @Override public synchronized void unlock() { if(lockBy==Thread.currentThread()){//7 lockcount--;//8 if(lockcount==0){//9 notify();//10 isLocked=false;//11 } } } @Override public void lockInterruptibly() throws InterruptedException { // TODO Auto-generated method stub } @Override public boolean tryLock() { // TODO Auto-generated method stub return false; } @Override public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { // TODO Auto-generated method stub return false; } @Override public Condition newCondition() { // TODO Auto-generated method stub return null; } }
下面結合例項來分析上面手動實現的可重入鎖,首先設計了一個Test類,定義了兩個函式a()和b(),在函式a()中加鎖並呼叫b()函式,在b()函式中,同樣進行加鎖操作。
當只有一個執行緒時:
- 進入函式a(),首先呼叫lock.lock()函式,執行步驟1,此時currentThread=thread0,執行步驟2,isLocked=false,currentThread=thread0,lockBy=null,並不進入while迴圈,則執行步驟4-6,isLocked=true,lockBy=thread0,lockcount=1
- 進入函式b(),同樣呼叫lock()函式,執行步驟1,此時currentThread=thread0,執行步驟2,isLocked=true,currentThread=lockBy,不滿足條件,並不進入while迴圈,則執行步驟4-6,isLocked=true,lockBy=thread0,lockcount=2
- 呼叫函式b()中的unlock()函式,執行步驟7,lockBy=thread0=Thread.currentThread,則執行步驟8,lockcount=1,退出函式
- 接著呼叫函式a()中的unlock()函式,執行步驟7,同樣滿足判斷,lockcount=0,執行步驟10-11,呼叫notify()函式通知其他執行緒,並設定isLocked變數為false。
當有多個執行緒競爭時:
通過比較currentThread變數(當前想要獲取鎖的執行緒)和lockBy(當前已經持有鎖的執行緒)進行比較,如果不相同,則呼叫wait()函式,直到有執行緒呼叫notify()通知。
package com.concur.class21; import java.util.concurrent.locks.Lock; public class Test { Lock lock=new MyLock(); public void a(){ lock.lock(); System.out.println("a"); b(); lock.unlock(); } public void b(){ lock.lock(); System.out.println("b"); lock.unlock(); } public static void main(String[] args) { Test test=new Test(); new Thread(new Runnable() { @Override public void run() { test.a(); } }).start(); } }
輸出結果:
a
b