ReentrantLock之AQS原理与源码详解

ReentrantLock和AQS的关系


ReentrantLock使用

ReentrantLock之AQS原理与源码详解_第1张图片

AbstractQueuedSynchronizer,抽象队列同步器;给大家画一个图先,看一下ReentrantLock和AQS之间的关系。
ReentrantLock之AQS原理与源码详解_第2张图片

AbstractQueuedSynchronizer为ReentrantLock的静态内部类
ReentrantLock之AQS原理与源码详解_第3张图片

lock()源码分析

图片描述

2、默认为非公平锁
图片描述

3、最终会调用AbstractQueuedSynchronizer子类NonfairSync.lock()方法;
ReentrantLock之AQS原理与源码详解_第4张图片

图片描述

线程1跑过来调用ReentrantLock的lock()方法尝试进行加锁,这个加锁的过程,直接就是用CAS操作将state值从0变为1。
如果之前没人加过锁,那么state的值肯定是0,此时线程1就可以加锁成功。
一旦线程1加锁成功了之后,就可以设置当前加锁线程是自己。所以大家看下面的图,就是线程1跑过来加锁的一个过程。
ReentrantLock之AQS原理与源码详解_第5张图片

可重入锁

state记录加锁次数,为0时释放锁

锁的互斥是如何实现的?

线程2跑过来一下看到,哎呀!state的值不是0啊?所以CAS操作将state从0变为1的过程会失败,因为state的值当前为1,说明已经有人加锁了!
接着线程2会看一下,是不是自己之前加的锁啊?当然不是了,“加锁线程”这个变量明确记录了是线程1占用了这个锁,所以线程2此时就是加锁失败。
接着,线程2会将自己放入AQS中的一个等待队列,因为自己尝试加锁失败了,此时就要将自己放入队列中来等待,等待线程1释放锁之后,自己就可以重新尝试加锁了
所以大家可以看到,AQS是如此的核心!AQS内部还有一个等待队列,专门放那些加锁失败的线程!
同样,给大家来一张图,一起感受一下:
ReentrantLock之AQS原理与源码详解_第6张图片

释放锁源码:

LockSupport.unpark(s.thread);
ReentrantLock之AQS原理与源码详解_第7张图片

Node存储等待线程队列

ReentrantLock之AQS原理与源码详解_第8张图片

参考资料https://juejin.im/post/5c07e5...

你可能感兴趣的:(面试,源码,aqs,java)