AQS中的公平锁和非公平锁

article/2025/9/27 5:55:04

正文

公平锁:多个线程按照申请锁的顺序去获得锁,线程会直接进入队列去排队,永远都是队列的第一位才能得到锁。

  • 优点:所有的线程都能得到资源,不会饿死在队列中。

  • 缺点:吞吐量会下降很多,队列里面除了第一个线程,其他的线程都会阻塞,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,是否是当前线程等等,都去思考下。

 

 


http://chatgpt.dhexx.cn/article/p6mmVh5n.shtml

相关文章

公平锁和非公平锁介绍

公平锁: 解释:多个线程按照申请锁的顺序执行,先来后到。 优点:所有的线程都能得到资源,不会饿死在队列中。 缺点:吞吐量会下降很多,队列里面除了第一个线程,其他的线程都会阻塞&a…

公平锁和非公平锁的详解

公平锁 加锁时考虑排队等待问题,按照申请锁的顺序,按照FIFO规则,先申请的线程先取得锁,其他线程进入队列等待锁的释放,当锁释放后,在队头的线程被唤醒。 非公平锁 加锁时不考虑排队等待问题,直接…

可重入锁的理解及公平锁和非公平锁的具体实现

可重入锁 首先结合以下两个例子理解以下可重入锁的概念。 /*** 可重入锁:* 1、可重复可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死锁,这样的锁就叫做可重入锁。* 2、是指在同一个线程在外层方法获取锁的时…

公平锁与非公平锁的核心原理

前言:大家好,我是小威,24届毕业生,在一家满意的公司实习。本篇文章是关于并发编程中AQS的独占模式和共享模式。 本篇文章记录的基础知识,适合在学Java的小白,也适合复习中,面试中的大佬&#x1…

公平锁和非公平锁介绍,为什么要“非公平”?

什么是公平和非公平 公平锁指的是按照线程请求的顺序,来分配锁;而非公平锁指的是不完全按照请求的顺序,在一定情况下,可以允许插队。但需要注意这里的非公平并不是指完全的随机,不是说线程可以任意插队,而…

图解ReentrantLock公平锁和非公平锁实现

概述 ReentrantLock是Java并发中十分常用的一个类,具备类似synchronized锁的作用。但是相比synchronized, 它具备更强的能力,同时支持公平锁和非公平锁。 公平锁: 指多个线程按照申请锁的顺序来获取锁,线程直接进入队列中排队&a…

Java面试突击:公平锁和非公平锁有什么区别?

从公平的角度来说,Java 中的锁总共可分为两类:公平锁和非公平锁。但公平锁和非公平锁有哪些区别?孰优孰劣呢?在 Java 中的应用场景又有哪些呢?接下来我们一起来看。 正文公平锁:每个线程获取锁的顺序是按照线程访问锁的先后顺序获取的&am…

浅谈ReentrantLock的公平锁和非公平锁的区别

前言 最近在看java并发编程这本书,已经看了点ReentrantLock的源码,以及之前有面试官问,公平锁和非公平锁有啥区别,我就只是从源码层面说了一下区别,但在性能上也有区别,今天就来说道说道。 公平与非公平 …

aqs原理初探以及公平锁和非公平锁实现

深入理解AQS 一,AQS1,ReentrantLock2,CAS3,AbstractQueuedSynchronizer3.1,FairSync3.2,NofairSync3.3,AQS中几个重要的相关参数3.4,Node 一,AQS AbstractQueuedSynchro…

图解ReentrantLock底层公平锁和非公平锁实现原理

💻在面试或者日常开发当中,经常会遇到公平锁和非公平锁的概念。 两者最大的区别如下👇 1️⃣ 公平锁:N个线程去申请锁时,会按照先后顺序进入一个队列当中去排队,依次按照先后顺序获取锁。就像下图描述的上…

ReentrantLock之公平锁和非公平锁详解

ReentrantLock是一个互斥锁,它具有synchronized相同的能力;但相比之下,ReentrantLock扩展性更强,比如实现了公平锁。 下面详细拆解下ReentrantLock的公平锁和非公平锁的实现。 JDK版本:1.8.0_40 公平锁 先看Reentr…

ReentrantLock中公平锁和非公平锁的区别

目录 背景知识 ReentrantLock的组成 概述 公平锁示意图 非公平锁示意图 源码解读 非公平锁 公平锁 代码对比 问题 知识扩展 tryLock方法 参考资料 背景知识 ReentrantLock的组成 首先看下ReentrantLock的组成结构。 公平锁和非公平锁主要是通过内部类FairSync和…

公平锁和非公平锁

Reentrant Re entrant,Re是重复、又、再的意思,entrant是enter的名词或者形容词形式,翻译为进入者或者可进入的,所以Reentrant翻译为可重复进入的、可再次进入的,因此ReentrantLock翻译为重入锁或者再入锁。 公平锁…

阿里面试官:说一下公平锁和非公平锁的区别?

点赞再看,养成习惯,微信搜索【三太子敖丙】关注这个互联网苟且偷生的工具人。 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点、资料以及我的系列文章。 前言 上次我们提到了乐观锁和悲观锁,那我们知道…

Ubuntu 手动安装 JDK8

文章目录 1. 下载2. 解压安装3. 配置环境变量 1. 下载 先去官网下载合适的版本,官网:https://www.oracle.com/java/technologies/downloads/archive/ 通过下载页面获取到下载链接后,可以直接在Ubuntu上使用wget下载,也可以先下载…

centos8安装jdk教程

文章目录 一、安装二、配置环境变量三.验证 一、安装 1、查看JDK软件包列表 yum search java | grep -i --color jdk2、选择版本安装 yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel或者如下命令安装jdk8所有文件 yum install -y java-1.8.0-openjdk*二、配置…

Java - JDK8安装及配置环境变量教程

Java - JDK8安装及配置环境变量教程 一、安装JDK教程 甲骨文官网下载JDK版本:windows64下载地址 下载完成后开始安装JDK:双击打开 点击下一步: 若不需要自定义路径,则安装到默认路径即可(安装的路径需记住&#xff0…

JDK8安装和环境配置

JDK8的安装和环境配置 一、JDK8下载二、安装三、环境配置 一、JDK8下载 官网下载: https://www.oracle.com/java/technologies/downloads/#java8-windows 二、安装 打开安装,一直下一步即可,可以在安装过程中更改安装地址,我放…

Java JDK 8的安装与配置

文章目录 前言1. 安装JDK 8Step1:选择JDK的版本Step2:选择系统平台Step3:下载安装包Step4:开始安装 2. 配置JDK 8Step1:配置“环境变量path” 前言 本教程是在Windows 64位平台上安装JDK 8版本。 1. 安装JDK 8 官网…

JDK8安装与环境配置

前言:在网上看了下JDK的安装与环境配置,发现很多视频以及博客的讲的都很复杂,对初学者很不友好。很多小白看到这些配置步骤都一脸懵,即使一步一步看着操作还是配置失败。这主要是因为很多博主配置了不需要的配置环境,让…