美文网首页并发编程
Lock底层原理解析-AQS-lock方法-03

Lock底层原理解析-AQS-lock方法-03

作者: 愤怒的奶牛 | 来源:发表于2020-04-29 23:46 被阅读0次

    前面我们做了一些预备知识,现在我们就开始来分析lock 接口。

    • Lock 接口定义


      image.png
    • demo

    // 重入锁
    private Lock lock = new ReentrantLock();
    public void add () {
            try {
                lock.lock();
                System.out.println(".......");
            }finally {
                lock.unlock();
            }
        }
    

    我们就从ReentrantLock 开始。

    • ReentrantLock
    /**
         * Creates an instance of {@code ReentrantLock}.
         * This is equivalent to using {@code ReentrantLock(false)}.
         */
        private final Sync sync;
        public ReentrantLock() {// 默认构造器
            sync = new NonfairSync();
        }
    

    这里呢,看不出啥东西,只知道 有个 对象叫 Sync 然后 被实例化 。sync = new NonfairSync();

    -内部类 Sync

    abstract static class Sync extends AbstractQueuedSynchronizer {
        abstract void lock();
        ....................
    }
    

    在 ReentrantLock 内部定义了一个 抽象的 内部类 Sync。继承 AbstractQueuedSynchronizer ,这个东西我们就叫他AQS了。

    • lock.lock(); // demo 代码点进去,我们就看到下面这段代码。
     public void lock() {
            sync.lock(); // NonfairSync 中的 lock
        }
    

    通过上面的分析我们知道 这里的 sync = new NonfairSync();

    • NonfairSync
    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 的值,state = 1 表示 获取锁成功。
                    setExclusiveOwnerThread(Thread.currentThread()); // 记录下获取锁的线程
                else // 没有获取锁成功的线程就 执行  acquire(1); 
                    acquire(1); 
            }
    
            protected final boolean tryAcquire(int acquires) {
                return nonfairTryAcquire(acquires);
            }
        }
    
    • compareAndSetState(0, 1)
    // AbstractQueuedSynchronizer
    
    /**
         * The synchronization state.
         */
    private volatile int state; // 默认是 0
    // expect = 0, update = 1
    protected final boolean compareAndSetState(int expect, int update) { 
            // See below for intrinsics setup to support this
            // stateOffset ,state 字段的内存地址值
            return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
        }
    

    通过 CAS 对 AbstractQueuedSynchronizer 中的 state 的值 更新,如果 更新成功,表示 当前线程获取锁成功,否则 阻塞,继续等待。这里就看出来 AQS 其实 是采用乐观锁的方式来 实现线程 的锁控制。

    我们大致来整理一下 我们在使用 Lock 接口来控制多线程的时候的 调用链:

    1. private Lock lock = new ReentrantLock();
    2. lock.lock();
    3. NonfairSync.lock();
      4.AbstractQueuedSynchronizer.compareAndSetState(0, 1)
    1. 创建 重入锁对象 Lock lock = new ReentrantLock();
    2. 调用 lock() 方法 ,lock.lock();
    3. ReentrantLock 中的lock 方法,调用的是 NonfairSync 对象的 lock() 方法。
    4. NonfairSync#lock() 使用 AQS 中的 compareAndSetState(0, 1) 方法 来更新 AQS 中 state 属性的值,更新为1 表示当前线程获取锁成功。

    上面我们分析了 lock 对象 中 lock 方法是如何 控制线程获取锁的,后面我们就接着分析,没有获取到锁的对象 都被 存放到哪里去了。

    相关文章

      网友评论

        本文标题:Lock底层原理解析-AQS-lock方法-03

        本文链接:https://www.haomeiwen.com/subject/tpoowhtx.html