读AQS源码-关于同步队列与锁的公平性

2023-05-16

先上部分源码:

public final void acquire(int arg) {
  if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

final boolean acquireQueued(final Node node, int arg) {
    boolean failed = true;
    try {
        boolean interrupted = false;
        for (;;) {
            final Node p = node.predecessor();
            if (p == head && tryAcquire(arg)) {
                setHead(node);
                p.next = null; // help GC
                failed = false;
                return interrupted;
            }
            if (shouldParkAfterFailedAcquire(p, node) &&
                parkAndCheckInterrupt())
                interrupted = true;
        }
    } finally {
        if (failed)
            cancelAcquire(node);
    }
}

private volatile int state;

AQS维护一个FIFO队列,用于存储获取同步状态失败的线程组成的节点,先进行获取动作的排在队前。既然是FIFO队列,AQS是如何实现非公平锁的?
注意到:同步队列维持的是唤醒顺序,不是获取锁的顺序,当然这二者在某些情况下可能等价,比如要获取锁的进程均已进入同步队列,那么唤醒顺序就是获得锁的顺序。
但是,对于其他情况,因为lock调用的是acquire模板方法,源码如上,看到在新线程每次获取锁时,先尝试获取锁,只有当失败了才会进入同步队列,这个试的过程就会导致非公平锁的产生,假如有如下场景:
1.A线程持有锁并作为同步队列的head存在,其后依次为BCD三个节点
2.E线程准备获取锁
3.A线程释放锁,同步状态加1,并会唤醒同步队列的后继节点中的线程,也就是B中的线程。
4.BCD自加入同步队列后就一直在进行自旋(检查前驱是否为head并尝试获取锁否则找到安全点并休息),此时从B的角度看,无非又是一次重复多次的自旋。
5.在B自旋检查条件时(前驱是否为head并尝试获取锁),E正好来了,E一上来就直接是
if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
此时B执行if (p == head && tryAcquire(arg))可能满足,E执行tryAcquire(arg)可能满足,就会出现争用。

6.如果E先执行成功(将volatile类型的state减1,那B就会因缓存一致性而无效其缓存而重新从内存中读取,发现state已满,不可获得),B失败,则产生非公平锁(B在同步队列等了好长时间却没有获得锁)
7.要实现公平锁,就要在tryAcquire(arg)中做文章,让新来的线程别瞎试,试之前先看同步队列有没有节点,没有再去尝试获取锁(BCD:没看见A后面我们几个排着队呢,你一新来的别瞎试,到后面排队)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

读AQS源码-关于同步队列与锁的公平性 的相关文章

  • Zigbee技术有哪些特点

    ZigBee的特点主要有以下八个方面 xff1a xff08 1 xff09 低功耗 xff1a 在低耗电待机模式下 xff0c 2节5号干电池可支持1个节点工作6 24个月 xff0c 甚至更长 这是ZigBee的突出优势 相比之下蓝牙可
  • Django接收自定义http header(转)--- request.META.get('HTTP_REGIONID')

    https www cnblogs com ajianbeyourself p 4104504 html With the exception of CONTENT LENGTH and CONTENT TYPE as given abov
  • http请求参数之Query String Parameters、Form Data、Request Payload

    在与server端进行数据传递时 xff0c 通常会用到GET POST方法进行参数提交 xff0c 而参数提交的方式 xff0c 通常取决于server端对数据的接收方式 本文对几种常见的参数提交方式进行归纳及简述 xff0c 这不是一篇
  • requests.api

    coding utf 8 34 34 34 requests api This module implements the Requests API copyright c 2012 by Kenneth Reitz license Apa
  • SUMMERY

    HOME pip pip ini http www cnblogs com kevingrace p 5252929 html
  • session

    class Session SessionRedirectMixin 34 34 34 A Requests session Provides cookie persistence connection pooling and config
  • Zookeeper学习之路 (一)初识

    Zookeeper学习之路 xff08 一 xff09 初识 目录 引言分布式协调技术分布式锁的实现 面临的问题分布式锁的实现者ZooKeeper概述ZooKeeper数据模型 ZooKeeper数据模型ZnodeZooKeeper中的时间
  • 更改conda install、pip install源

    由于tensorflow暂不支持python3 7 xff0c 因此博主需要将python3 7降回到python3 6 xff0c 但是默认源下载实在太慢 转载于 https blog csdn net dream allday arti
  • VMware虚拟机配置、连接MobaXterm

    连接MobaXterm 在上一篇博客中详细讲述了 VMware 虚拟机的安装 xff0c 这里演示一下虚拟机连接 MobaXterm xff0c 虚拟机连接 MobaXterm 以后就可以直接在 MobaXterm 里面执行虚拟机操作 xf
  • 详细描述虚拟机安装JDK并配置环境变量的全过程

    Linux虚拟机安装JDK步骤 1 登录虚拟机以后查看防火墙状态 xff0c 要求关闭防火墙 查看防火墙指令 xff1a systemctl status firewalld 禁用防火墙指令 xff1a systemctl disable
  • 多线程经典练习题

    线程练习题 1 用共享资源的方式实现 生产者 仓库 消费者的模式 注意线程安全 线程通信 span class token keyword public span span class token keyword class span sp
  • 目标检测1——YOLO数据标注以及xml转为txt文件脚本实战

    目录 1 数据标注 2 xml批量转为txt文件 1 数据标注 利用Yolov5进行目标检测的过程中 我们需要对数据进行标注 这里我们利用的是labelImg脚本进行数据标注的 labelImg主要用于yolov5数据标注工具 深度学习文档
  • JSON数据清理(详解)

    二 JSON数据清洗 1 JSON数据 仅以两条数据为例 span class token number 1593136280858 span span class token operator span span class token
  • Spark-SQL常用内置日期时间函数

    Spark SQL常用内置日期时间函数 一 获取当前时间 1 current date 获取当前日期时间格式 xff1a yyyy MM dd spark span class token punctuation span span cla
  • Java连接hive

    注意 xff1a 需要开启hive服务 首先建一个maven工程 xff0c 导入依赖包导pom xml span class token tag span class token tag span class token punctuat
  • 基于 Mapnik 的地图服务器

    目录 一 简介二 安装 PostgreSQL 数据库和 PostGIS 扩展三 下载地图样式表和上传地图数据四 将地图数据导入 PostgresSQL五 生成 Mapnik Stylesheet六 安装 mapnik七 地图生成1 安装 E
  • Linux 添加互信

    一 添加主机列表 span class token function vi span etc hosts 添加内容 ip1 hoatnmae1 ip2 hoatnmae2 ip3 hoatnmae3 二 秘钥分发 2 1 生成秘钥 ssh
  • Python升级后 yum 无法正常使用

    问题 xff1a 原因 xff1a 这是因为 yum 采用 Python 作为命令解释器 xff0c 这可以从 usr bin yum 文件中第一行 usr bin python 发现 而 python 版本之间兼容性不太好 xff0c 使
  • CDH开启高可用后,NameNode主备节点切换

    查看nn1的状态 hdfs haadmin getServiceState nn1 span class token comment standby span hdfs haadmin getServiceState nn2 span cl
  • git分支从master切换到main

    git分支从master切换到main 背景 本地当前分支为master xff0c 远程仓库为main xff0c 且远程仓库与本地仓库有 unrelated histories这样的问题 xff0c 如远程仓库有README md但本地

随机推荐

  • Docker学习第三天——Docker网络

    文章目录 摘要Linux 网络命名空间Docker bridge网络容器之间的Link容器的端口映射容器网络之host和none多容器复杂应用的部署多机器通信 摘要 Docker学习之旅第三天 Docker 网络 看完这篇文章将收获dock
  • 大津阈值法(OTSU)功能实现

    具体的公式推导参见冈萨雷斯 数字图像处理 Otsu方法又称最大类间方差法 xff0c 通过把像素分配为两类或多类 xff0c 计算类间方差 xff0c 当方差达到最大值时 xff0c 类分割线 xff08 即灰度值 xff09 就作为图像分
  • cas-server服务端搭建

    1 下载cas服务代码 xff0c https github com apereo cas overlay template tree 5 3 2 使用idea工具打开cas overlay template 5 3包 xff0c 使用ma
  • 自适应阈值canny边缘检测(功能实现)

    学习记录 1 概述 canny边缘检测是一种特别常用且性能优秀的边缘检测算法 xff0c 相比于普通的边缘检测算法 xff0c canny获得的边缘较细且具有连续的边缘轮廓 xff0c 为之后的一系列图像处理带来极大的便利 canny边缘检
  • OpenCV实现图像基础频率域滤波

    写在前面 xff1a 刚开始接触数字图像处理频率域滤波时 xff0c 很是陌生 xff0c 感觉这个技术使用范围很窄 xff0c 不如空域直接处理来的实在 xff0c 最近看书发现有些情况又不得不在频率域中进行操作 xff0c 个人感觉图像
  • OpenCV实现同态滤波

    同态滤波是属于图像增强的一个小算法 xff0c 其原理和代码实现在众多博客中均有提及 xff0c 再此 xff0c 只对学习中一些自认为有用的知识点进行总结 实现和学习过程中的一些总结 xff1a 同态滤波类似于灰度变换 xff0c 都是对
  • OpenCV实现击中击不中变换和形态学细化

    1 击中击不中变换 1 1 HMT概述 形态学Hit or Miss是形状检测基本工具 xff0c 只要结构元设置得当 xff0c 就可以检测一些基本的形状图案 xff0c HMT变换只能作用于二值图像 xff0c 结构元 xff08 核
  • OpenCV综合练习1——水瓶水位线合格检测

    数字图像处理综合练习 水瓶水位线合格检测 马上就要转到学习深度学习的主干线了 xff0c 这也是大势所趋 xff0c 但不能忘本 xff0c 传统图像处理的知识也是非常重要的 xff0c 特此记录一下之前学习时做过的小练习 整个项目的资源放
  • 目标检测学习1——iou计算与非极大值抑制NMS

    刚开始学习目标检测 xff0c 都是在学习一些经典的目标检测框架 xff0c 个人认为在大量阅读和理解别人现成的代码时 xff0c 也要懂得去动手模仿 xff0c 尝试着去修改别人的代码 xff0c 即使是自己抄一遍别人的代码 xff0c
  • OpenCV实现按指定间隔抽取视频中的图像帧

    习惯了C 43 43 语言的OpenCV突然用Python语言OpenCV还是感觉有点不适应 xff0c 但是慢慢在写的过程中 xff0c 觉得Python语言的风格也挺美的 但自己的写的还是很丑 xff0c 晚上回宿舍的剩余时间 xff0
  • 深度估计berHu损失函数和语义分割带权值交叉熵损失函数

    深度估计berHu损失函数和语义分割带权值交叉熵损失函数 最近在做联合深度估计和语义分割的深度学习算法 xff0c 深度估计默认使用的是L1 loss xff0c 语义分割使用的是普通的交叉熵损失函数 xff0c 继续改进模型对于指标的提升
  • 游览器是如何工作的

    游览器是如何工作的 浏览器的主要功能浏览器的主要构成一次网络请求浏览器发生了什么 xff1a 如果请求使用了HTTPS那么流程会有什么不同 xff1f 总结 浏览器的主要功能 浏览器的主要功能是将用户选择得web资源呈现出来 xff0c 它
  • OSG QT 完整附加依赖项(.lib)

    OSG QT 完整附加依赖项 lib 可在VS等需要添加附加依赖项的环境使用 注 xff1a OSG版本 xff1a 3 6 4 xff1b QT版本 xff1a 5 9 8 带d的为debug xff0c 不带d的release省掉了Qt
  • Ubuntu登陆账户后自动运行VNCserver

    问题 xff1a 远程桌面时 xff0c 如果重启远程Ubuntu xff0c 则VNC会话失效 解决 xff1a 一个解决的方法就是用putty将重启的Ubuntu登陆入账户后 xff0c 再开启VNC会话 为了方便 xff0c 可以设置
  • RAP与RARP原理

    ARP与RARP都属于网络层协议 xff0c 但是他们是为了解决链路层的帧转发问题 xff0c ARP的功能是将IP解析成MAC地址 xff0c 而RARP则相反 ARP 地址解析协议 xff08 Address Resolution Pr
  • eyeshot官方样例说明

    Eyeshot 12 例子 1 wings拖动按钮改变机翼的尺寸参数 xff0c 并导出到step文件 2 snaptogrid鼠标画平面 xff0c 类似于CATIA的多段线功能 3 sceneeditor控制灯光点和变换位置 xff0c
  • Python爬虫实现获取股票信息并保存到文件(亲测可运行)

    主要参考了北京理工大学嵩天老师的视频 xff0c 因老师所讲的网址已做更改 xff0c 将获取股票列表信息和股票价格的网站做了更改 xff0c 用到了beautiful soup库 xff0c re库 xff0c requests库 xff
  • 为什么要内存对齐?

    CPU访问非对齐的内存时为何需要多次读取再拼接 xff1f 首先简单说一下何为内存对齐 例如 xff0c 当cpu需要取4个连续的字节时 xff0c 若内存起始位置的地址可以被4整除 xff0c 那么我们称其对齐访问 反之 xff0c 则为
  • 读AQS源码-关于shouldParkAfterFailedAcquire函数的返回值

    先上源码 final boolean acquireQueued final Node node int arg boolean failed 61 true try boolean interrupted 61 false for fin
  • 读AQS源码-关于同步队列与锁的公平性

    先上部分源码 xff1a public final void acquire span class token punctuation span int arg span class token punctuation span span