AQS中的公平锁和非公平锁
正文
公平锁:多个线程按照申请锁的顺序去获得锁,线程会直接进入队列去排队,永远都是队列的第一位才能得到锁。
优点:所有的线程都能得到资源,不会饿死在队列中。
缺点:吞吐量会下降很多,队列里面除了第一个线程,其他的线程都会阻塞,cpu唤醒阻塞线程的开销会很大。
非公平锁:多个线程去获取锁的时候,会直接去尝试获取,获取不到,再去进入等待队列,如果能获取到,就直接获取到锁。
优点:可以减少CPU唤醒线程的开销,整体的吞吐效率会高点,CPU也不必取唤醒所有线程,会减少唤起线程的数量。
缺点:你们可能也发现了,这样可能导致队列中间的线程一直获取不到锁或者长时间获取不到锁,导致饿死。
我举个例子给他家通俗易懂的讲一下的,想了好几天终于在前天跟三歪去肯德基买早餐排队的时候发现了怎么举例了。
现在是早餐时间,敖丙想去kfc搞个早餐,发现有很多人了,一过去没多想,就乖乖到队尾排队,这样大家都觉得很公平,先到先得,所以这是公平锁咯。
那非公平锁就是,敖丙过去买早餐,发现大家都在排队,但是敖丙这个人有点渣的,就是喜欢插队,那他就直接怼到第一位那去,后面的鸡蛋,米豆都不行,我插队也不敢说什么,只能默默忍受了。
但是偶尔,鸡蛋也会崛起,叫我滚到后面排队,我也是欺软怕硬,默默到后面排队,就插队失败了。
其实在大家经常使用的ReentrantLock中就有相关公平锁,非公平锁的实现了。
大家还记得我在乐观锁、悲观锁章节提到的Sync类么,是ReentrantLock他本身的一个内部类,他继承了AbstractQueuedSynchronizer,我们在操作锁的大部分操作,都是Sync本身去实现的。
Sync呢又分别有两个子类:FairSync和NofairSync
他们子类的名字就可以见名知意了,公平和不公平那又是怎么在代码层面体现的呢?
公平锁:
你可以看到,他加了一个hasQueuedPredecessors的判断,那他判断里面有些什么玩意呢?
代码的大概意思也是判断当前的线程是不是位于同步队列的首位,是就是返回true,否就返回false。
我总觉得写到这里就应该差不多了,但是我坐下来,静静的思考之后发现,还是差了点什么。
上次聊过ReentrantLock了,但是AQS什么的我都只是提了一嘴,一个线程进来,他整个处理链路到底是怎样的呢?
公平锁到底公平不公平呢?让我们一起跟着丙丙走进ReentrantLock的内心世界。
上面提了这么多,我想你应该是有所了解了,那一个线程进来ReentrantLock这个渣男是怎么不公平的呢?(默认是非公平锁)
我先画个图,帮助大家了解下细节:
ReentrantLock的Sync继承了AbstractQueuedSynchronizer也就是我们常说的AQS
他也是ReentrantLock加锁释放锁的核心,大致的内容我之前一期提到了,我就不过多赘述了,他们看看一次加锁的过程吧。
A线程准备进去获取锁,首先判断了一下state状态,发现是0,所以可以CAS成功,并且修改了当前持有锁的线程为自己。
这个时候B线程也过来了,也是一上来先去判断了一下state状态,发现是1,那就CAS失败了,真晦气,只能乖乖去等待队列,等着唤醒了,先去睡一觉吧。
A持有久了,也有点腻了,准备释放掉锁,给别的仔一个机会,所以改了state状态,抹掉了持有锁线程的痕迹,准备去叫醒B。
这个时候有个带绿帽子的仔C过来了,发现state怎么是0啊,果断CAS修改为1,还修改了当前持有锁的线程为自己。
B线程被A叫醒准备去获取锁,发现state居然是1,CAS就失败了,只能失落的继续回去等待队列,路线还不忘骂A渣男,怎么骗自己,欺骗我的感情。
诺以上就是一个非公平锁的线程,这样的情况就有可能像B这样的线程长时间无法得到资源,优点就是可能有的线程减少了等待时间,提高了利用率。
现在都是默认非公平了,想要公平就得给构造器传值true。
ReentrantLock lock = new ReentrantLock(true);
说完非公平,那我也说一下公平的过程吧:
线A现在想要获得锁,先去判断下state,发现也是0,去看了看队列,自己居然是第一位,果断修改了持有线程为自己。
线程b过来了,去判断一下state,嗯哼?居然是state=1,那cas就失败了呀,所以只能乖乖去排队了。
线程A暖男来了,持有没多久就释放了,改掉了所有的状态就去唤醒线程B了,这个时候线程C进来了,但是他先判断了下state发现是0,以为有戏,然后去看了看队列,发现前面有人了,作为新时代的良好市民,果断排队去了。
线程B得到A的召唤,去判断state了,发现值为0,自己也是队列的第一位,那很香呀,可以得到了。
总结:
总结我不说话了,但是去获取锁判断的源码,箭头所指的位置,现在是不是都被我合理的解释了,当前线程,state,是否是0,是否是当前线程等等,都去思考下。
AQS中的公平锁和非公平锁相关推荐
- java中ReentrantLock实现,公平锁和非公平锁,AQS并发队列,
一般在java中,遇到并发的时候,我们很多时候可能会使用synchronized关键字来实现锁,但是synchronized关键字有一定的缺陷(比如无法实现类似读锁.非公平),而Lock可以实现.在j ...
- AQS中公平锁和非公平锁区别,你知道么
点击关注公众号,实用技术文章及时了解 来源:blog.csdn.net/weixin_43823391/ article/details/114259418 一.概念 注意:因为ReentrantLo ...
- 闲聊AQS面试和源码解读---可重入锁、LockSupport、CAS;从ReentrantLock源码来看公平锁与非公平锁、AQS到底是怎么用CLH队列来排队的?
AQS原理可谓是JUC面试中的重灾区之一,今天我们就来一起看看AQS到底是什么? 这里我先整理了一些JUC面试最常问的问题? 1.Synchronized 相关问题以及可重入锁 ReentrantLo ...
- AQS之公平锁和非公平锁
AQS之公平锁和非公平锁(二) 一.概念 注意:因为ReentrantLock 类可以实现公平锁和非公平锁,所以本文的讲解以该类为主. 1.1 公平锁 多个线程按照申请锁的顺序去获得锁,线程会直接 ...
- ReentrantLock中公平锁和非公平锁的区别
目录 背景知识 ReentrantLock的组成 概述 公平锁示意图 非公平锁示意图 源码解读 非公平锁 公平锁 代码对比 问题 知识扩展 tryLock方法 参考资料 背景知识 ReentrantL ...
- aqs原理初探以及公平锁和非公平锁实现
深入理解AQS 一,AQS 1,ReentrantLock 2,CAS 3,AbstractQueuedSynchronizer 3.1,FairSync 3.2,NofairSync 3.3,AQS ...
- 【并发】ReentrantLock中公平锁和非公平锁的理解
[前言] ReentrantLock 是在JavaSE5之后,并发包中新增了Lock接口用来实现锁功能,它提供了与synchronized关键字类似的同步功能.同时ReentrantLock也是重入锁 ...
- java 共享锁 独占锁_java中的公平锁、非公平锁、可重入锁、递归锁、自旋锁、独占锁和共享锁...
一.公平锁与非公平锁 1.1 概述 公平锁:是指多个线程按照申请锁的顺序来获取锁. 非公平锁:是指在多线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取到锁,在高并发的情 ...
- 多线程中的公平锁和非公平锁
一.公平锁与非公平锁概念: 锁Lock分为"公平锁"和"非公平锁",公平锁表示线程获取锁的顺序是按照线程加锁的顺序分配的,即先来先得的FIFO先进先出的 ...
最新文章
- 面向对象软件设计的“开—闭”原则
- 最萌办公室采访 | 网易程序员灵魂大拷问(文末有福利)
- iOS开发之pch文件的正确使用
- 【收藏】ArcGIS 10.8 for Desktop 完整安装教程(含win7/8/10 32/64位+下载地址+亲测可用+汉化)
- [BUUCTF-pwn]——[第六章 CTF之PWN章]stack
- 数据结构与算法:排序算法的稳定性以及各性能比较python实现
- 服务器连接不稳定fifa,fifa服务器链接异常
- 高并发负载均衡——网络协议原理
- c#日期转换周几_C#中获取任意日期为星期几三种方法分享
- [贪心|双指针] leetcode 11 盛最多水的容器
- el-table表格数据没有刷新
- 百度云搜索引擎森林战士_纯干货:网盘搜索引擎整理
- 即插即用!Batch Transformer
- IEEE期刊最新的影响因子
- MS5837-30BA 水深水压传感器简单介绍
- 小雷的冰茶几---3386
- 妙用分部积分处理双重积分
- 语音搜索引擎--Midomi
- 白杨SEO:从5118站长工具备案内参发现百度SEO批量建站优化玩法
- proguard 配置简介