1. 程式人生 > >java 手動實現一個可重入鎖

java 手動實現一個可重入鎖

手動實現一個可重入鎖

下面程式碼給出了一個手動實現的可重入鎖,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&&currentThread!=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()函式中,同樣進行加鎖操作。

當只有一個執行緒時:

  1. 進入函式a(),首先呼叫lock.lock()函式,執行步驟1,此時currentThread=thread0,執行步驟2,isLocked=false,currentThread=thread0,lockBy=null,並不進入while迴圈,則執行步驟4-6,isLocked=true,lockBy=thread0,lockcount=1
  2. 進入函式b(),同樣呼叫lock()函式,執行步驟1,此時currentThread=thread0,執行步驟2,isLocked=true,currentThread=lockBy,不滿足條件,並不進入while迴圈,則執行步驟4-6,isLocked=true,lockBy=thread0,lockcount=2
  3. 呼叫函式b()中的unlock()函式,執行步驟7,lockBy=thread0=Thread.currentThread,則執行步驟8,lockcount=1,退出函式
  4. 接著呼叫函式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