1. 程式人生 > >鎖之ReentrantLock

鎖之ReentrantLock

獲取 ima images 操作 同步 zab ext 增加 private

源碼結構圖

技術分享圖片

Lock源碼

public interface Lock {

  //獲取鎖
  void lock();

 /**
  *當前線程的鎖沒有中斷才能獲取鎖
  * if (Thread.interrupted())
  *        throw new InterruptedException();
  */
  void lockInterruptibly() throws InterruptedException;

    //獲取鎖是否成功。true表示獲取到鎖,false表示沒有獲取到鎖
  boolean tryLock();

     // 嘗試獲取鎖,並等待指定的時間
   boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

   // 釋放鎖
   void unlock();

   // LOCK條件
   Condition newCondition();
}

ReentrantLock源碼

public class ReentrantLock implements Lock, java.io.Serializable {
  // 同步器,是整個鎖機制的實現者
  private final Sync sync;

  // 定義的抽象靜態內部類。實現基本的功能
    abstract static class Sync extends AbstractQueuedSynchronizer {
         // 抽象方法。由公平鎖和非公平鎖自己實現
        abstract void lock();

            // 釋放鎖
            protected final boolean tryRelease(int releases) {
                  // 鎖的計數器。釋放一次計數器減1,直到為0,則整個鎖完全釋放,才能被其他線程獲取該鎖。
            int c = getState() - releases;
                        // 此類型鎖是可重入鎖。因此是以thread為粒度的。必須判斷當前線程是否與持有鎖線程一致。
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
                        // 當鎖的計數器為0時,整個鎖釋放。
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

                // 默認實現的一個非公平鎖的獲取嘗試獲取方法
                final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
                        // 如果鎖的計數器為0,則表示沒有鎖。
            if (c == 0) {
                            //  compareAndSetState方法實際調用的是unsafe.compareAndSwapInt(this, stateOffset, expect, update);
                // 直接操作的JVM。並給當前線程持有鎖。
                                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
                        // 如果計數器不為0,但當前線程就是持有鎖的線程。則鎖的計數器增加。
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
                        // 如果計數器不為0,同時當前線程不是持有鎖的線程。則加鎖失敗。
            return false;
        }
     }

  // 非公平所的實現器
  static final class NonfairSync extends Sync {

             // 加鎖。
         final void lock() {
            if (compareAndSetState(0, 1)) //非公平加鎖
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1); // 如果加鎖不成功,則放入隊列
        }

          // 試著加鎖
          protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }

    }

    // 公平鎖
    static final class FairSync extends Sync {

             // 加鎖,隊列
         final void lock() {
            acquire(1);
        }

                // 試著加鎖
                protected final boolean tryAcquire(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;
        }

    }

}    

AbstractQueuedSynchronizer源碼

 // 存儲隊列鎖的存儲node.是一個雙向的鏈表結構。
 static final class Node {
   // 前一個node
   volatile Node prev;
     // 後一個node
     volatile Node next;
     // 該node所對應的線程
     volatile Thread thread;        
 }

 // 整個隊列鎖的第一個node.
 private transient volatile Node head;

 // 整個隊列鎖的第後個node.
 private transient volatile Node tail;

 // 鎖的狀態。計數器
 private volatile int state;

 // 加鎖的關鍵點。通過navtive 方法unsafe直接操作CPU。
 protected final boolean compareAndSetState(int expect, int update) {
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
 }

總結

Lock這種以類的方式來實現鎖的機制。
優點:
1.加鎖和釋放鎖獨立,可以分開來控制。
2.tryLock的方法可以嘗試加鎖,不會像sychnorized一致阻塞。
3.實現了公平鎖和非公平鎖。sychnorized只能是非公平鎖。

缺點:
1.增加了代碼的復雜度。
2.相比sychnorized的自動加鎖和釋放鎖,Lock需要手動,容易忘記,從而出現重大的隱患。

經過JDK的不斷更新,sychnorized與lock的性能相差不大,官方建議使用sychnorized方法加鎖。

鎖之ReentrantLock