鎖的重入是指同一個執行緒可以多次獲取同一個鎖,synchronize是隱式的可重入鎖,ReentrantLock通過程式碼實現了鎖的重入:
final boolean nofairTryAcquire(int acquires){
final Thread current=Thread.currentThread();
int c=getState();
if(c==0){
if(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;
}
從上面的程式碼中,可以一目瞭然的發現,當獲取鎖的執行緒與擁有鎖的執行緒是同一個執行緒時,僅會對狀態進行累加。so easy ,並沒有什麼難度。那接下來我們想一下,如何實現公平所和非公平鎖,上面的程式碼是非公平鎖的實現方式。那如何實現公平鎖那?所謂的公平鎖就是所有獲取鎖的執行緒都要按照“先來後到”的順序獲取鎖。假設執行緒B在阻塞佇列中,等待獲取鎖,如果還有一個執行緒A在B的前面,那麼B就要讓A先獲取鎖。因此在B嘗試獲取鎖之前,只要判斷一下它是否還有前驅的佇列即可。很easy吧:
final boolean fairTryAcquire(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;
}
公平所和非公平鎖的各自優勢是什麼那?公平鎖很好理解,可以防止出現執行緒飢餓現象,每一個執行緒都有機會獲取到鎖。非公平鎖可能會導致執行緒飢餓,但是我們一般使用非公平鎖,因為非公平鎖可以減少上下文的切換,提高效率。