Lockt体系
一、Lock体系
1、什么是Lock体系
首先我们要明确:java提供了两种方式来加锁,
- 一种是关键字:synchronized: 是java底层支持的。
- 一种是concurrent包下的lock锁: 是jdk实现。
Lock体系:
- Lock体系其实是另一类锁的集合,是jdk提供的一种除synchronized之外的加锁方式。
- Lock是一个接口,它在java.util.concurrent.locks包下,并且这个包下有很多Lock接口的实现类。
说到java.util.concurrent.locks包,我们先来看看java.util.concurrent包,它是一个解决并发问题的包,通常用在并发编程中。
2、java.util.concurrent包
下图的思维导图中,我们可以看到java.util.concurrent包下都有哪些类或接口;其中java.util.concurrent.locks也是java.util.concurrent这个包下的一个成员,它就构成了所谓的Lock体系。里边包含接口以及实现类。
对于java.util.concurrent包下的其他成员见博客: https://blog.youkuaiyun.com/yuiop123455/article/details/108759427.,本篇博客主要说一下Lock锁的原理。
3、Lock锁
LOCK锁相对于synchronized加锁方式来说,因为Lock锁是jdk提供的,所以需要什么时候加锁是由开发人员来决定的,只需要调用相应的API就可以实现加锁释放锁操作:
- lock.lock():加锁
- lock.unlock():释放锁
lock锁的代码流程:
我们通过上面代码可以看出lock锁相对于synchronized加锁操作来说确实灵活了很多。那麽两种锁的差异到底有哪些呢?
4、synchronized和Lock锁的对比:
另外,lock锁在实现上也变得灵活了许多:
1>策略变灵活了
- tryLock():尝试加锁
- lockInterruptibly()
- tryLock(超时时间):在一定的超时时间内尝试加锁
2>实现锁的种类也多了(接口方便自己实现)实现的锁也变灵活了!
提供了:
- ReadwriteLock.(读写锁)
- ReentrantLock(可重入锁)
- ReentrantReadWriteLock(可重入的读写锁)
- 以及用户可以自己实现锁(比如带自旋功能的锁)
二、Lock锁原理
Lock锁的实现原理:AQS(AbstractQueueSynchronizer),即抽象的队列式同步器。
1、AQS
AQS的实现:
AQS也是在java.util.concurrent.locks包下。AQS:队列式的同步器
队列的实现:(1)双端队列,(2)AQS中保存队列的头尾节点;见下图
Node里边保存线程的引用;
AQS里边实现了一个队列,AQS里边保存了这个队列的头节点和尾节点,这个队列里边保存了许多线程的状态和方法,比如通过队列的一些方法可以获取/设置某个线程的状态(compareAndSetState())
---------->也就是AQS是一个线程安全的双向队列,并将线程引用保存起来。
AQS的实现原理:
实现原理(获取锁的过程):
- 双端队列保存线程及线程同步状态。
- 并通过CAS提供设置同步状态的方法(AQS是基于CAS实现的,见下面具体说)。如ReentranLock实现时调用lock.lock()操作,会不停的设置线程同步状态.
AQS提供的模板方法可以分为3类:
- 独占式获取与释放同步状态;
- 共享式获取与释放同步状态;
- 查询同步队列中等待线程情况;
2、Lock锁的实现原理
我们通过底层源码来看一下(仔细看截图哦):
Syn类中调用了很多方法都是继承了AQS。
所以Lock相关的实现类都是基于AQS实现的,AQS又是基于CAS实现的。
简而言之,LOCK锁及AQS的实现原理见下图:
加锁:
通过调用Lock.lock()方法进行加锁操作的时候,等于说执行加锁操作,所有的线程在竞争锁的时候先把线程的引用对象加到AQS队列中去;如果获取到这个锁,就把该线程的同步状态设置为已经获取到锁的状态,其他线程获取的话就获取不成功。当前线程推出之后,其他线程再竞争并获取到锁之后再设置线程的同步状态。
设置完线程的同步状态(lock.lock())就进队列,执行完lock.unlock()就出队列,相当于不停的进队列出队列
3、Lock锁的特点
1)提供公平锁和非公平锁: 是否按照入队的顺序设置线程的同步状态,即:多个线程申请加锁操作时,是否按照时间顺序来加锁
例如:new操作的时候传一个true就是公平锁,传一个false就是非公平锁,不传就默认为false(非公平锁)
2)AQS提供的独占式、共享式设置同步状态(独占锁、共享锁)------》本质是设置线程的同步状态
- 独占式:只允许一个线程获取到锁
- 共享式:一定数量的线程共享式获取锁
3)带Reentrant关键字的lock包下的API:可重入锁
允许多次获取同一个Lock对象的锁