AQS中ReentrantLock的上锁原理
描述
- AQS全称“AbstractQueuedSynchronized”,意为抽象队列同步器
- JUC中常用到的ReentrantLock,CcountDownLatch底层都是基于AQS来实现的加锁和释放锁等功能。
- AQS是Java并发包的基础
使用
ReentrantLock上锁原理
- 当一个线程尝试用ReentrantLock的lock()方法进行加锁。
- 首先AQS有一个核心变量state,它是int类型,用来代表加锁的状态,初始为0,代表没加锁。AQS还有一个变量用来记录加锁的是哪个线程,默认变量值为null
- 当加锁时,线程1跑过来调用ReentrantLock方法尝试加锁,这个加锁的过程,用的是CAS操作将state的值从0变成1.如果之前没人加过锁,那么state的值肯定是0,此时线程1就可以加锁成功。
- 一旦线程1加锁成功了,就可以设置加锁线程是自己
- ReentrantLock只是一个外层API,内核的锁机制依赖于AQS组件实现
- 而ReentrantLock的可重入锁,本质就是把state的值给累加1
锁如何互斥
- 当线程2跑过来后发现state的值不是0,所以CAS操作将state从0变成1的过程会失败。接着线程2会看一下是不是自己之前加锁了。加锁线程变量” 会标明是哪个线程占用了锁,所以线程2的可重入操作也失败。
- 此时,线程2会将自己放入AQS的等待队列中,这个等待队列专门用来放加锁失败的线程。
如何释放锁
- 线程1在执行完自己的业务逻辑后,就会释放锁。
- 释放锁的过程:将AQS的state变量值递减1,知道state为0,彻底释放锁,会将加锁线程变量也值为null
- 线程2发现state可操作后,AQS会将其进行上锁,此时线程2获得锁~