当前位置: 首页 > news >正文

对ReentrantLock的公平性进行测试

ReentrantLock公平性实现原理

在ReentrantLock类内部定义了一个内部类Sync以及两个实现NonfairSync和FairSync,它们内部定义了锁获取和释放的逻辑,下面我列出了两种同步类的代码,通过观察两个代码的差异就可以看到公平性是如何实现的。
NonfairSync和FairSync的差异如下:
差异1:非公平锁在获取锁时增加一条shortcut尝试快速获取锁
差异2:公平锁在尝试获取锁前需保证当前线程位于AQS队列的头部

  static final class NonfairSync extends Sync {private static final long serialVersionUID = 7316153563782823691L;/*** Performs lock.  Try immediate barge, backing up to normal* acquire on failure.*/final void lock() {if (compareAndSetState(0, 1))     // 差异1:非公平锁在一开始可以直接尝试获取锁,而不需要再经过acquire->tryAcquire->nonfairTryAcquire这样长的路径setExclusiveOwnerThread(Thread.currentThread());elseacquire(1);}protected final boolean tryAcquire(int acquires) {return nonfairTryAcquire(acquires);}final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {// 差异2:非公平锁在获取锁时,不需要判断当前线程是否处在队头if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0) // overflowthrow new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}
}
static final class FairSync extends Sync {private static final long serialVersionUID = -3000897897090466540L;final void lock() {// 差异1:公平锁不能在一开始直接获取锁,否则可能先于队列中的等待线程获取到锁,破坏了公平性acquire(1);}/*** Fair version of tryAcquire.  Don't grant access unless* recursive call or no waiters or is first.*/protected final boolean tryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {// 差异2:公平锁实现中,线程处于队头才有资格获取锁,保证了公平性if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0)throw new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}
}

总结一下,公平性的实现主要通过在获取锁之间增加一句检查实现,具体来说,调用hasQueuedPredecessors方法检查当前线程是否在队头,只有在队头的线程才能获取到锁,这样,如果新来一个线程,在它入队前是不会拿到锁的,从而保证了线程获取锁的顺序 = 线程申请锁的顺序,也就是说实现了公平性。

ReentrantLock公平性测试

在上一节,说到了ReentrantLock的公平性,如果是公平锁,线程获取锁的顺序 = 线程访问锁的顺序,如果是非公平锁,线程获取锁的顺序 ≠ 线程访问锁的顺序,那也就是说,如果使用非公平锁,一个还没有被加入到队列的新线程可能会抢走早已在队列中等待的线程的锁。基于这个思路,我们来写一个程序来验证ReentrantLock的公平性。
具体步骤如下:

  • 主线程获取锁但不释放;
  • 创建若干打印线程(打印字符p)并运行,这些线程不能拿到锁,因而被依次放到队列中等待;
  • 主线程释放锁,同时立即创建几个新打印线程(打印字符s)运行。

假如是公平锁,那么新打印线程必定会入队等待,按序获取锁,那么最终打印的字符s永远不可能出现在字符p之前;但如果是非公平锁,新打印线程有机会与旧打印线程同时竞争锁,那么这时候字符s可能会出现在字符p之前。
最终的程序如下:

import org.junit.jupiter.api.Test;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;import static org.junit.jupiter.api.Assertions.*;class ReentrantLockTest {@Testpublic void test() throws InterruptedException {ReentrantLock lock = new ReentrantLock(true);final int threadNum = 50;// 主线程先获取锁lock.lock();// 将几个线程在锁队列中排队List<Thread> threads = new ArrayList<>();for (int i = 0; i < threadNum; i++) {Thread thread = new Thread(() -> {try {lock.lock();System.out.printf(Thread.currentThread().getName() + " ");} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}, "p");thread.start();threads.add(thread);}// 主线程释放锁,再创建几个线程竞争锁Thread.sleep(200);lock.unlock();List<Thread> threads1 = new ArrayList<>();for (int i = 0; i < threadNum * 2; i++) {Thread thread = new Thread(() -> {try {lock.lock();System.out.printf(Thread.currentThread().getName() + " ");} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}, "s");thread.start();threads.add(thread);}for (Thread thread : threads) {thread.join();}// 预计successor-number可能输出在number之前}
}

fair为true时输出结果为:

p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p p s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s 

fair为false时输出结果为:

p p p p p s p s s p p s p s s s p p p p p s s p p p s p s p p p s p s p p p s p s p p p s p p p s p p p p p p p s p p p s p s p s s p p s p s p p p s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s 

相关文章:

对ReentrantLock的公平性进行测试

ReentrantLock公平性实现原理 在ReentrantLock类内部定义了一个内部类Sync以及两个实现NonfairSync和FairSync&#xff0c;它们内部定义了锁获取和释放的逻辑&#xff0c;下面我列出了两种同步类的代码&#xff0c;通过观察两个代码的差异就可以看到公平性是如何实现的。 Nonf…...

LabVIEW之TDMS文件

在很多场合&#xff0c;早期的LabVIEW版本不得不借助常规的数据库来做一些数据管理工作&#xff0c;但常规数据库对于中高速数据采集显然是不合适的&#xff0c;因为高速数据采集的数据量非常大&#xff0c;用一般的数据库无法满足存储数据的要求。 直到TDM(Technical Data Ma…...

DeepSeek 实现原理探析

DeepSeek 实现原理探析 引言 DeepSeek 是一种基于深度学习的智能搜索技术&#xff0c;它通过结合自然语言处理&#xff08;NLP&#xff09;、信息检索&#xff08;IR&#xff09;和机器学习&#xff08;ML&#xff09;等多领域的技术&#xff0c;旨在提供更加精准、智能的搜索…...

2021 年 9 月青少年软编等考 C 语言五级真题解析

目录 T1. 问题求解思路分析T2. 抓牛思路分析T3. 交易市场思路分析T4. 泳池思路分析T1. 问题求解 给定一个正整数 N N N,求最小的 M M M 满足比 N N N 大且 M M M 与 N N N 的二进制表示中有相同数目的 1 1 1。 举个例子,假如给定 N N N 为 78 78 78,二进制表示为 …...

洛谷网站: P3029 [USACO11NOV] Cow Lineup S 题解

题目传送门&#xff1a; P3029 [USACO11NOV] Cow Lineup S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 前言&#xff1a; 这道题的核心问题是在一条直线上分布着不同品种的牛&#xff0c;要找出一个连续区间&#xff0c;使得这个区间内包含所有不同品种的牛&#xff0c;…...

编程领域的IO模型(BIO,NIO,AIO)

目前对于市面上绝大多数的应用来说&#xff0c;不能实现的业务功能太少了。更多的是对底层细节&#xff0c;性能优化的追求。其中IO就是性能优化中很重要的一环。Redis快&#xff0c;mysql缓冲区存在的意义。都跟IO有着密切关系。IO其实我们都在用&#xff0c;输入输出流这块。…...

DeepSeek和ChatGPT的对比

最近DeepSeek大放异彩&#xff0c;两者之间有什么差异呢&#xff1f;根据了解到的信息&#xff0c;简单做了一个对比。 DeepSeek 和 ChatGPT 是两种不同的自然语言处理&#xff08;NLP&#xff09;模型架构&#xff0c;尽管它们都基于 Transformer 架构&#xff0c;但在设计目标…...

Pyqt 的QTableWidget组件

QTableWidget 是 PyQt6 中的一个表格控件&#xff0c;用于显示和编辑二维表格数据。它继承自 QTableView&#xff0c;提供了更简单的方式来处理表格数据&#xff0c;适合用于需要展示结构化数据的场景。 1. 常用方法 1.1 构造函数 QTableWidget(parent: QWidget None)&#x…...

4. 【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--什么是微服务--微服务设计原则与最佳实践

相比传统的单体应用&#xff0c;微服务架构通过将大型系统拆分成多个独立的小服务&#xff0c;不仅提升了系统的灵活性和扩展性&#xff0c;也带来了许多设计和运维上的挑战。如何在设计和实现微服务的过程中遵循一系列原则和最佳实践&#xff0c;从而构建一个稳定、高效、易维…...

网络安全威胁框架与入侵分析模型概述

引言 “网络安全攻防的本质是人与人之间的对抗&#xff0c;每一次入侵背后都有一个实体&#xff08;个人或组织&#xff09;”。这一经典观点概括了网络攻防的深层本质。无论是APT&#xff08;高级持续性威胁&#xff09;攻击、零日漏洞利用&#xff0c;还是简单的钓鱼攻击&am…...

树和二叉树_7

树和二叉树_7 一、leetcode-102二、题解1.引库2.代码 一、leetcode-102 二叉树的层序遍历 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 样例输入&#xff1a;root [3,9,20,null,nu…...

不同标签页、iframe或者worker之间的广播通信——BroadcastChannel

BroadcastChannel是一个现代浏览器提供的 API&#xff0c;用于在同一浏览器的不同浏览上下文&#xff08;如不同的标签页、iframe 或者 worker&#xff09;之间进行消息传递。它允许你创建一个广播频道&#xff0c;通过该频道可以在不同的浏览上下文之间发送和接收消息。 Broa…...

开源CodeGPT + DeepSeek-R1 是否可以替代商业付费代码辅助工具

开源CodeGPT + DeepSeek-R1 是否可以替代商业付费代码辅助工具 背景与研究目的 在快速发展的软件开发领域,代码辅助工具已成为提高开发效率和质量的关键。然而,商业付费工具如通义灵码和腾讯AI代码助手,尽管功能强大,但其高昂的成本和许可证限制,使得许多企业寻求更具吸…...

AUTOSAR汽车电子嵌入式编程精讲300篇-基于FPGA的CAN FD汽车总线数据交互系统设计

目录 前言 汽车总线以及发展趋势 汽车总线技术 汽车总线发展趋势 CAN FD总线国内外研究现状 2 系统方案及CAN FD协议分析 2.1系统控制方案设计 2.2 CAN FD总线帧结构分析 2.2.1数据帧分析 2.2.2远程帧分析 2.2.3过载帧分析 2.2.4错误帧分析 2.2.5帧间隔分析 2.3位…...

STC51案例操作

案例 1&#xff1a;LED 闪烁 功能描述&#xff1a;通过操作 P1 口寄存器&#xff0c;让连接在 P1.0 引脚的 LED 以一定间隔闪烁。 #include <reg51.h>// 延时函数 void delay(unsigned int time) {unsigned int i, j;for (i 0; i < time; i)for (j 0; j < 123; …...

多光谱技术在华为手机上的应用发展历史

2018 年&#xff0c;华为 P20 系列首次搭载 5 通道色温传感器&#xff0c;可帮助手机在不同光照条件下保持画面色彩一致性。 2020 年&#xff0c;华为 P40 系列搭载 8 通道多光谱色温传感器&#xff08;实际为 11 通道&#xff0c;当时只用 8 个通道检测可见光&#xff09;&am…...

C语言:函数栈帧的创建和销毁

目录 1.什么是函数栈帧2.理解函数栈帧能解决什么问题3.函数栈帧的创建和销毁的过程解析3.1 什么是栈3.2 认识相关寄存器和汇编指令3.3 解析函数栈帧的创建和销毁过程3.3.1 准备环境3.3.2 函数的调用堆栈3.3.3 转到反汇编3.3.4 函数栈帧的创建和销毁 1.什么是函数栈帧 在写C语言…...

NLP_[2]_文本预处理-文本数据分析

文章目录 4 文本数据分析1 文件数据分析介绍2 数据集说明3 获取标签数量分布4 获取句子长度分布5 获取正负样本长度散点分布6 获取不同词汇总数统计7 获取训练集高频形容词词云8 小结 4 文本数据分析 学习目标 了解文本数据分析的作用.掌握常用的几种文本数据分析方法. 1 文…...

【工具篇】深度揭秘 Midjourney:开启 AI 图像创作新时代

家人们,今天咱必须好好唠唠 Midjourney 这个在 AI 图像生成领域超火的工具!现在 AI 技术发展得那叫一个快,各种工具层出不穷,Midjourney 绝对是其中的明星产品。不管你是专业的设计师、插画师,还是像咱这种对艺术创作有点小兴趣的小白,Midjourney 都能给你带来超多惊喜,…...

从O(k*n)到O(1):如何用哈希表终结多层if判断的性能困局

【前言】   本文将以哈希表重构实战为核心&#xff0c;完整展示如何将传统条件匹配逻辑(上千层if-else判断)转化为O(1)的哈希表高效实现。通过指纹验证场景的代码级解剖&#xff0c;您将深入理解&#xff1a;   1.哈希函数设计如何规避冲突陷阱   2.链式寻址法的工程实现…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

Mysql8 忘记密码重置,以及问题解决

1.使用免密登录 找到配置MySQL文件&#xff0c;我的文件路径是/etc/mysql/my.cnf&#xff0c;有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...