队列同步器AbstractQueuedSynchronizer

  队列同步器AbstractQueuedSynchronizer简称AQS,是锁和其他同步组件的基石,它通过一个volatile修饰的int变量表示同步状态,通过内置FIFO队列完成资源获取线程的排队,

并发包作者(Doug Lea)希望它成为大部分同步需求的基础。通过继承AQS,使用它提供的状态改变方法compareAndSetState(int expect, int update)

可以保证状态改变是安全的。

  下面我们来分析下ReentrantLock如何通过AbstractQueuedSynchronizer实现加锁和解锁,分析下加锁和解锁轨迹。

   1. 加锁方法lock()的调用轨迹如下:

  (1) ReentrantLock:lock(),源码如下

 1 public class ReentrantLock implements Lock, java.io.Serializable {
 2     private static final long serialVersionUID = 7373984872572414699L;
 3     /** Synchronizer providing all implementation mechanics */
 4     private final Sync sync;  
 5   /**
 6    * 获取锁.
 7    */
 8   public void lock() {
 9       sync.lock();
10   }
11   /**
12    * 此锁的同步控制的基础  
13    * Base of synchronization control for this lock. Subclassed
14    * into fair and nonfair versions below. Uses AQS state to
15    * represent the number of holds on the lock.
16    */
17   abstract static class Sync extends AbstractQueuedSynchronizer {
18     //省略内部实现
19   }
20 }

       (2) 默认非公平锁,NonfairSync:lock(),源码如下

/**
     * 默认构造函数创建非公平锁 
    * Creates an instance of {@code ReentrantLock}.
     * This is equivalent to using {@code ReentrantLock(false)}.
     */
     public ReentrantLock() {
         sync = new NonfairSync();
     }

   /**
    *  非公平锁实现,Sync的子类
    * Sync object for non-fair locks
    */
   static final class NonfairSync extends Sync {
       private static final long serialVersionUID = 7316153563782823691L;
 
       /**
        * 执行锁定
      * Performs lock.  Try immediate barge, backing up to normal
        * acquire on failure.
        */
       final void lock() {
           if (compareAndSetState(0, 1))//通过CAS设置同步状态,只有预见state为0才设置为1
               setExclusiveOwnerThread(Thread.currentThread());
           else
              acquire(1);
       }
   }

 (3)在NonfairSync的lock方法中调用AbstractQueuedSynchronizer的compareAndSetState(int expect, int update)方法,源码如下

    /**
     * CAS原子方式更新state变量,具有volatile读和写内存语义
     */
    protected final boolean compareAndSetState(int expect, int update) {
        // See below for intrinsics setup to support this
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

  2. 解锁方法unlock()的调用轨迹如下。

  (1)ReentrantLock:unclock(),源码如下

    /**
     * 此处通过子类对象sync调用父类方法,没什么特别
     */
    public void unlock() {
        sync.release(1);
    }

  (2)AbstractQueuedSynchronizer:unclock(),源码如下

/**
 * 调用AbstractQueuedSynchronizer的release(int arg)方法
 */
public final boolean release(int arg) {
    //tryRelease(arg)真正开始释放锁的地方,调用子类Sync的tryRelease方法,该方法做了具体实现,在接下来调用链的第(3)步中说明
    if (tryRelease(arg)) {
        Node h = head;
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);
        return true;
    }
    return false;
}

  (3)Sync:tryRelease(),源码如下

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);//释放锁的最后写volatile变量state,根据volatile的happens-before原则,其他读取锁的线程将立即可见
    return free;
}

 

posted on 2023-03-16 16:20  我的笔记本  阅读(27)  评论(0)    收藏  举报