博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
多线程透析--JUC的锁机制、锁原理CAS、AQS
阅读量:2048 次
发布时间:2019-04-28

本文共 2319 字,大约阅读时间需要 7 分钟。

多线程透析–JUC的锁机制、锁原理

其实之前博客中就已经提到了JUC,今天详细的透析下JUC的锁机制和锁原理。

在JDK1.1~1.2 的时候 只有synchronize锁,此时的锁只是一个重量级锁,所谓的重量级锁我个人理解就是线程在使用资源时需要通过OS线程队列进行调度,只有在获取锁(没有其他线程占用锁)的情况下才能进行。这类锁一般具有排他性,所以也叫悲观锁。

而早期的synchronize不管你是否是多线程竞争关系,都会同样的采取重量级锁这一套。这样再简单的线程操作中,就很影响效率。

在JDK 1.5 之后推出了JUC包,这个包提供了很多原子类,用于保证多线程同步。

JUC的锁机制和锁原理

JUC的提供了很多五花八门的锁,简单介绍下:
ReentrantLock:和synchronized具有差不多的语义,独占锁,同时只有一个线程能获得锁。
ReentrantReadWriteLock:读写锁。读允许共享,写独占。适用于读频繁的场景。
CountDownLatch:闭锁。使用场景类似比赛鸣枪,在没有鸣枪之前所有的运动员(线程)都必须等待。说白了就是使用于一个或多个线程等待某一个条件成立了,触发运行。
Semaphore:信号量。使用场景类似通行证,通行证数量有限,拿到证的才能通行。
CyclicBarrier:周期障碍。语义上和CountDownLatch有点类似,只有几个线程打到一个共同的状态之后,触发后续动作继续。不同在于1.达到共同状态后,可以指定一个后续触发的线程对象。2.周期性意味着可以周期运行。
FutureTask:带有返回值的异步执行。
等等

这些锁的都会在不同场景中被使用,这些同步措施可以统称为sync 同步器框架。

以上各种锁的使用场景后面有机会在介绍。

JUC锁原理(底层)

老样子还是举例说明:JUC的实现类ReentrantLock锁。
ReentrantLock锁 和 synchronize锁的区别在之前就已经说过了,现在重点说下JUC的锁机制和锁原理。

先简单说下JUC底层实现原理是CAS和AQS,CAS在上面文章已经说过了,是一种自旋锁的实现方式。简单看下ReentrantLock实现代码:

final Lock lock = new ReentrantLock(false);    public void study() throws InterruptedException {
for (int i = 0; i <2 ; i++) {
try {
lock.lock(); // 等待5秒钟拿不到锁就返回false System.out.println(Thread.currentThread().getName()+":我正在学习"); //Thread.sleep(2000); }catch (Exception e){
}finally {
lock.unlock(); } } }

这里用到了ReentrantLock锁对线程进行了同步操作。那么我们就看下这个lock怎么处理的?

在这里插入图片描述
进到lock方法实现类去看看:
在这里插入图片描述
这里就是Sync同步器类的调用。继续进去看下:
在这里插入图片描述
进去之后我们可以看到这里面有两个实现类:FairSync 和 NonfairSync 这两个分表就是公平锁和非公平锁的实现类。进到默认的非公平锁类:
在这里插入图片描述
这代码什么意思呢?

if (compareAndSetState(0, 1))

判断是否设置锁成功,看下怎么判断的?

在这里插入图片描述
这里是不是就看到熟悉的字样了compareAndSwapInt (CAS)。

如果成功了就把该线程设置为当前线程(线程暂用),如果不成就进行 acquire(1)操作(好像有点废话了),那么就核心看下 acquire(1);内部实现:

在这里插入图片描述
在这里插入图片描述
这里我们可以看到if(;;)操作,就是无限循环,这里什么意思呢?就是说如果lock设置锁没有成功,那么就无限的循环去尝试设定锁,直到成果为止。看到这是不是明白了JUC底层原理是CAS了。

AQS实现原理

AQS是什么呢?
以上说的JUC包下所有的实现都是继承AQS(AbstractOwnableSynchronizer)类实现。
上面说的ReentrantLock的lock刚才看到了,是基于NonfairSync 。
在这里插入图片描述
那我们再看下这个类继承关系:
在这里插入图片描述

那么我们先看看AQS是怎么实现的呢?

在这里插入图片描述
看这张图:
AQS实现了一个框架实现原理CAS+voalitle,框架中定义基础属性state(一个锁状态标识,根据不同的锁机制定位含义)。还实现了一个双向链表队列框架(CLH)。关于这个队列的所有操作都是关于CAS实现。

当一个线程来的时候会把自己做成一个node去排队,当有很多线程需要排队竞争队列tail(尾巴)位置时,就是用到了CAS实现。

然后我们通过源码在一起看下JUC的AQS:

在这里插入图片描述
再看下setExclusiveOwnerThread:
在这里插入图片描述
我们可以看到占用锁的操作正是AbstractOwnableSynchronizer。

然后我们再看下如果没有设置锁成功呢?

刚才我们看了acquire方法,无限的循环去尝试设置。

在这里插入图片描述
在这里插入图片描述
AQS正是利用CAS将node加到双向链表队列中。
关于JUC,还有很多同步工具:
在这里插入图片描述

转载地址:http://ljhof.baihongyu.com/

你可能感兴趣的文章
"NetworkError: 400 Bad Request - http://172.16.47.117:8088/rhip/**/####t/approval?date=976
查看>>
ie8 加载不到js 报SCRIPT1028: 缺少标识符、字符串或数字 ;SCRIPT5009: “anorectaSearch”未定义
查看>>
mybatis 根据 数据库表 自动生成 实体
查看>>
win10将IE11兼容ie10
查看>>
checkbox设置字体颜色
查看>>
第一篇 HelloWorld.java重新学起
查看>>
ORACLE表空间扩张
查看>>
orcal 循环执行sql
查看>>
web.xml配置监听器,加载数据库信息配置文件ServletContextListener
查看>>
结构型模式之桥接模式(Bridge)
查看>>
行为型模式之备忘录模式(Memento)
查看>>
行为型模式之观察者模式(Observer)
查看>>
行为型模式之状态模式(State)
查看>>
行为型模式之策略模式(Strategy)
查看>>
行为型模式之模板方法模式(TemplateMethod)
查看>>
行为型模式之访问者模式(Visitor)
查看>>
大小端详解
查看>>
source insight使用方法简介
查看>>
<stdarg.h>头文件的使用
查看>>
C++/C 宏定义(define)中# ## 的含义 宏拼接
查看>>