死磕源碼系列(ReentrantLock)

前言

  • 在高併發領域,ReentrantLock有着普遍的用處,防止多線程帶來的併發問題
  • 對於源碼,不少人和我一開始同樣都以爲很是神祕
  • 此次我將對ReentrantLock進行全方面的揭祕

核心

  • AbstractQueuedSynchronizer
    • AQS是JDK實現的CAS同步器。裏面的核心是state和兩個node
    • state標識同步器如今的狀態,node做爲隊列串聯同步器中的節點
    • 使用volatile保證參數的可見性
volatile Node prev;
volatile Node next;
private volatile int state;

總體結構

  • ReentrantLock 調用內部類Sync,Sync繼承AbstractQueuedSynchronizer

總體流程

  • ReentrantLock調用內部類Sync的acquire方法,底層走的是AbstractQueuedSynchronizer,AbstractQueuedSynchronizer會嘗試獲取鎖,獲取失敗以後會加入隊列中,而後節點自旋去獲取鎖,一旦成功就將本身的節點至於頭部,而後退出。
  • cas實現(compareAndSet)。jdk9以前使用的是unsafe,jsk9以後使用的是varHandler。

核心代碼

AQS:node

public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
  • tryAcquire是第一次嘗試獲取所,公平鎖和非公平鎖的區別只是判斷本身節點是否除了head節點外仍是在本身前面的,校驗的是公平鎖,不校驗的是非公平鎖
  • addWaiter是節點加入到隊列中
  • acquireQueued裏面執行的就是自旋操做
final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            //自旋開始
            for (;;) {
                final Node p = node.predecessor();
                //嘗試開始獲取鎖
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

釋放鎖

protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }
相關文章
相關標籤/搜索