java重入鎖、公平鎖和非公平鎖

haofengpingjieli發表於2019-01-19
鎖的重入是指同一個執行緒可以多次獲取同一個鎖,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;
    }

公平所和非公平鎖的各自優勢是什麼那?公平鎖很好理解,可以防止出現執行緒飢餓現象,每一個執行緒都有機會獲取到鎖。非公平鎖可能會導致執行緒飢餓,但是我們一般使用非公平鎖,因為非公平鎖可以減少上下文的切換,提高效率。

相關文章