多线程 6 —— Lock体系、Lock锁原理(AQS)

一、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.csdn.net/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对象的锁

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值