javalock(四)AQS派生类之Semphore逐行注释
简单概括:
Semphore是一把共享锁(即读锁),即实现了AQS的tryAcquireShared&&tryReleaseShared函数
Semphore的逻辑是这样:
创建semphore的时候会初始化一个锁容量即permits,即最多同时允许permits个线程获取读锁资源。AQS的state在semphore中表示锁资源的剩余容量。Semphore.tryAcquireShared就是如果锁资源剩余容量大于0则表示可以成功获取锁,然后锁资源容量减一,Semphore的tryReleaseShared就是锁资源容量+1。
笔记:
semphore没有锁所有者的概念,只有资源剩余量的概念,也就是说不管你是谁,只要资源还有剩余,那么就允许访问,也就是说一个线程可以获取多次资源
import java.util.Collection;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;public class Semaphore implements java.io.Serializable {private static final long serialVersionUID = -3222578661600680210L;private final Sync sync;abstract static class Sync extends AbstractQueuedSynchronizer {private static final long serialVersionUID = 1192457210091910933L;Sync(int permits) {//state就是表示锁资源剩余量setState(permits);}final int getPermits() {return getState();}//尝试获取共享锁资源。while cas方式扣减,准确说是:do{}while(!CAS)//获取锁资源的逻辑就是:如果锁资源剩余容量大于0就允许立即获得锁而无需入aqs队列排队//反之则获取失败,返回false//semphore没有锁所有者的概念,只有资源剩余量的概念//也就是说不管你是谁,只要资源还有剩余,那么就允许访问//也就是说一个线程可以获取多次资源final int nonfairTryAcquireShared(int acquires) {for (;;) {//笔记:getState是非并发安全的,但是没关系,//因为getState的返回值只是用来快速判断是否有资源剩余//真正决定能否成功获得锁的还是cas(available,remainging)这个操作//也就是说这里是一个乐观的做法:先扣减,再写回,如果冲突了就重试//通过getState获取资源剩余量int available = getState();//先计算要扣减的资源量int remaining = available - acquires;//如果remaining小于0表示资源剩余量小于0则,此时无法成功获取锁,所以返回负数//如果compareAndSetState(available, remaining)成功则表明资源剩余量大于0//并且资源扣减成功,此时remaing大于等于0,表示获取锁成功,所以返回非负数if (remaining < 0 ||compareAndSetState(available, remaining))return remaining;//走到这里则进入下一轮循环重试}}//尝试释放锁资源,也是do{}while(!cas)方式增加锁资源//因为是共享锁,且没有所有者的概念,所以可以一个线程多次释放,//每次释放都会锁资源+1,甚至能无线多次释放,然后就能无限获取了,也就是卡bug了//如下所示:信号量最初资源容量限制为2,但是因为没有锁所有者的概念以及上限检测//所以直接release(100)即增加100个令牌,这样就能获取102个令牌而不会阻塞// Semaphore sem=new java.util.concurrent.Semaphore(2);// sem.release(100);// for(int i=0;i<102;i++){// sem.acquire();// }protected final boolean tryReleaseShared(int releases) {for (;;) {//读取锁资源状态int current = getState();//计算更新后的锁资源量int next = current + releases;if (next < current) throw new Error("Maximum permit count exceeded");//cas方式更新锁资源状态if (compareAndSetState(current, next))return true;//走到这里则进入下一轮循环重试}}//扣减锁资源,也是通过do{}while(!CAS)方式更新final void reducePermits(int reductions) {for (;;) {int current = getState();int next = current - reductions;if (next > current) throw new Error("Permit count underflow");if (compareAndSetState(current, next))return;}}//清空锁资源。就是把state设置为0,也是通过do{}while(!CAS)方式更新final int drainPermits() {for (;;) {int current = getState();if (current == 0 || compareAndSetState(current, 0))return current;}}}static final class NonfairSync extends Sync {private static final long serialVersionUID = -2694183684443567898L;NonfairSync(int permits) {super(permits);}//非公平方式获取锁资源:就是如果有锁资源剩余容量大于0就允许立即获得锁而无需入aqs队列排队protected int tryAcquireShared(int acquires) {return nonfairTryAcquireShared(acquires);}}static final class FairSync extends Sync {private static final long serialVersionUID = 2014338818796000944L;FairSync(int permits) {super(permits);}//公平方式获取锁资源:先来先服务的原则。//也就是说只要aqs队列不为空则说明在本线程之前有其他线程已经在排队了//公平的原则就是先来先服务,所以这里就直接返回false表示获取锁失败//一旦tryAcquireShared返回失败,则aqs会把该节点丢到aqs list的最末尾protected int tryAcquireShared(int acquires) {for (;;) {//判断是有在此之前有其他线程等待获取锁资源(即信号量)if (hasQueuedPredecessors())//如果有则返回false表获取锁资源失败return -1;//如果在此之前没有其他线程等待获取锁资源(即信号量)//则通过do{}while(!CAS)扣减锁资源int available = getState();int remaining = available - acquires;if (remaining < 0 ||compareAndSetState(available, remaining))return remaining;}}}public Semaphore(int permits) {sync = new NonfairSync(permits);}public Semaphore(int permits, boolean fair) {sync = fair ? new FairSync(permits) : new NonfairSync(permits);}//下面的函数都输对sync的一个简单封装,所以下面的函数就没注释了,一眼就能看明白public void acquire() throws InterruptedException {sync.acquireSharedInterruptibly(1);}public void acquireUninterruptibly() {sync.acquireShared(1);}public boolean tryAcquire() {return sync.nonfairTryAcquireShared(1) >= 0;}public boolean tryAcquire(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));}public void release() {sync.releaseShared(1);}public void acquire(int permits) throws InterruptedException {if (permits < 0) throw new IllegalArgumentException();sync.acquireSharedInterruptibly(permits);}public void acquireUninterruptibly(int permits) {if (permits < 0) throw new IllegalArgumentException();sync.acquireShared(permits);}public boolean tryAcquire(int permits) {if (permits < 0) throw new IllegalArgumentException();return sync.nonfairTryAcquireShared(permits) >= 0;}public boolean tryAcquire(int permits, long timeout, TimeUnit unit)throws InterruptedException {if (permits < 0) throw new IllegalArgumentException();return sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));}public void release(int permits) {if (permits < 0) throw new IllegalArgumentException();sync.releaseShared(permits);}public int availablePermits() {return sync.getPermits();}public int drainPermits() {return sync.drainPermits();}protected void reducePermits(int reduction) {if (reduction < 0) throw new IllegalArgumentException();sync.reducePermits(reduction);}public boolean isFair() {return sync instanceof FairSync;}public final boolean hasQueuedThreads() {return sync.hasQueuedThreads();}public final int getQueueLength() {return sync.getQueueLength();}protected Collection<Thread> getQueuedThreads() {return sync.getQueuedThreads();}public String toString() {return super.toString() + "[Permits = " + sync.getPermits() + "]";}
}相关文章:
javalock(四)AQS派生类之Semphore逐行注释
简单概括: Semphore是一把共享锁(即读锁),即实现了AQS的tryAcquireShared&&tryReleaseShared函数Semphore的逻辑是这样: 创建semphore的时候会初始化一个锁容量即permits,即最多同时允许permits个…...
【C语言】头文件”“和<>的详解
前言 作者在刚开始学C语言的时候,都是用的< >去引用头文件,但在学习STM32的时候发现,程序中大量使用" "去引用双引号。 那么二者有什么区别呢? 无论使用哪种方式,头文件的目的都是为了引用你需要的文件供你编程使…...
Elasticsearch:什么是信息检索?
信息检索定义 信息检索 (IR) 是一种有助于从大量非结构化或半结构化数据中有效、高效地检索相关信息的过程。信息(IR)检索系统有助于搜索、定位和呈现与用户的搜索查询或信息需求相匹配的信息。 作为信息访问的主要形式,信息检索是每天使用…...
Spark-Streaming容错语义
一、背景 为了理解Spark Streaming提供的语义,我们先回顾西Spark RDD的基本容错语义学。 RDD是一个不可变的、确定性可重新计算的分布式数据集。每个RDD都记住在容错输入数据集上用于创建它的确定性操作的沿袭。如果RDD的任何分区由于工作节点故障而丢失ÿ…...
2024年12月陪玩系统-仿东郊到家约玩系统是一种新兴的线上预约线下社交、陪伴系统分享-优雅草央千澈-附带搭建教程
2024年12月陪玩系统-仿东郊到家约玩系统是一种新兴的线上预约线下社交、陪伴系统分享-优雅草央千澈-附带搭建教程 产品介绍 仿东郊到家约玩系统是一种新兴的线上预约,线下社交、陪伴、助娱、助攻、分享、解答、指导等服务模式,范围涉及电竞、运动、音乐…...
GUI07-学工具栏,懂MVC
MVC模式,是天底下编写GUI程序最为经典、实效的一种软件架构模式。当一个人学完菜单栏、开始学习工具栏时,就是他的一生中,最适合开始认识 MVC 模式的好时机之一。这节将安排您学习: Model-View-Controller 模式如何创建工具栏以及…...
【进程篇】04.进程的状态与优先级
一、进程的状态 1.1 进程的状态 1.1.1 并行与并发 • 并行: 多个进程在多个CPU下分别,同时进行运行 • 并发: 多个进程在一个CPU下采用进程切换的方式,在一个时间片内,让多个进程都得以推进 1.1.2 时间片的概念 LInux/windows这些民用级别…...
ElasticSearch 数据聚合与运算
1、数据聚合 聚合(aggregations)可以让我们极其方便的实现数据的统计、分析和运算。实现这些统计功能的比数据库的 SQL 要方便的多,而且查询速度非常快,可以实现近实时搜索效果。 注意: 参加聚合的字段必须是 keywor…...
科研学习|论文解读——智能体最新研究进展
从2024-12-13到2024-12-18的45篇文章中精选出5篇优秀的工作分享 Can Modern LLMs Act as Agent Cores in Radiology~Environments? Achieving Collective Welfare in Multi-Agent Reinforcement Learning via Suggestion Sharing A systematic review of norm emergence in …...
面试小札:Java后端闪电五连鞭_8
1. Kafka消息模型及其组成部分 - 消息(Message):是Kafka中最基本的数据单元。消息包含一个键(key)、一个值(value)和一个时间戳(timestamp)。键可以用于对消息进行分区等…...
java error(2)保存时间带时分秒,回显时分秒变成00:00:00
超简单,顺带记录一下 1.入参实体类上使用注释:JsonFormat(pattern “yyyy-MM-dd”) 导致舍弃了 时分秒的部分。 2.数据库字段对应的类型是 date。date就是日期,日期就不带时分秒。 3.返参实体类使用了JsonFormat(pattern “yyyy-MM-dd”) 导…...
计算机毕业设计python+spark+hive动漫推荐系统 漫画推荐系统 漫画分析可视化大屏 漫画爬虫 漫画推荐系统 漫画爬虫 知识图谱 大数据毕设
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
数字IC后端设计实现篇之TSMC 12nm TCD cell(Dummy TCD Cell)应该怎么加?
TSMC 12nm A72项目我们需要按照foundary的要求提前在floorplan阶段加好TCD Cell。这个cell是用来做工艺校准的。这个dummy TCD Cell也可以等后续Calibre 插dummy自动插。但咱们项目要求提前在floorplan阶段就先预先规划好位置。 TSCM12nm 1P9M的metal stack结构图如下图所示。…...
(8)YOLOv6算法基本原理
一、YOLOv6 模型原理 发布日期:2022年6月 作者:美团技术团队 骨干网络:参考了 RepVGG 的设计,将重参数化能力进行补强,增强了模型结构的重参数化能力。使用了深度可分离卷积和跨阶段连接等技术,旨在提升…...
LNMP+discuz论坛
0.准备 文章目录 0.准备1.nginx2.mysql2.1 mysql82.2 mysql5.7 3.php4.测试php访问mysql5.部署 Discuz6.其他 yum源: # 没有wget,用这个 # curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo[rootlocalhost ~]#…...
在linux系统的docker中安装GitLab
一、安装GitLab: 在安装了docker之后就是下载安装GitLab了,在linux系统中输入命令:docker search gitlab就可以看到很多项目,一般安装第一个,它是英文版的,如果英文不好可以安装twang2218/gitlab-ce-zh。 …...
Python面试常见问题及答案12
问题: 请解释Python中的GIL(全局解释器锁)是什么? ○ 答案: GIL是Python解释器中的一种机制,用于确保任何时候只有一个线程在执行Python字节码。这在多线程场景下可能影响性能优化,但对于单线程…...
从0-1开发一个Vue3前端系统页面-9.博客页面布局
本节主要实现了博客首页界面的基本布局并完善了响应式布局,因为完善了响应式布局故对前面的页面布局有所改动,这里会将改动后的源码同步上传。 1.对页面头部的用户信息进行设计和美化 布局设计参考 :通常初级前端的布局会通过多个div划分区域…...
[手机Linux] 六,ubuntu18.04私有网盘(NextCloud)安装
一,LNMP介绍 LNMP一键安装包是一个用Linux Shell编写的可以为CentOS/RHEL/Fedora/Debian/Ubuntu/Raspbian/Deepin/Alibaba/Amazon/Mint/Oracle/Rocky/Alma/Kali/UOS/银河麒麟/openEuler/Anolis OS Linux VPS或独立主机安装LNMP(Nginx/MySQL/PHP)、LNMPA(Nginx/MySQ…...
白话java设计模式
创建模式 单例模式(Singleton Pattern): 就是一次创建多次使用,它的对象不会重复创建,可以全局来共享状态。 工厂模式(Factory Method Pattern): 可以通过接口来进行实例化创建&a…...
开源项目常见安装故障的系统性排查与解决
开源项目常见安装故障的系统性排查与解决 【免费下载链接】ComfyUI-Manager ComfyUI-Manager is an extension designed to enhance the usability of ComfyUI. It offers management functions to install, remove, disable, and enable various custom nodes of ComfyUI. Fur…...
城通网盘限速破解:ctfileGet让下载效率提升10倍的技术革命
城通网盘限速破解:ctfileGet让下载效率提升10倍的技术革命 【免费下载链接】ctfileGet 获取城通网盘一次性直连地址 项目地址: https://gitcode.com/gh_mirrors/ct/ctfileGet 在数字化协作日益频繁的今天,网盘已成为信息传递的重要枢纽。然而城通…...
3个步骤,让猫抓帮你轻松捕获网页视频资源
3个步骤,让猫抓帮你轻松捕获网页视频资源 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 你是否曾经遇到过这样的情况?在网…...
数据库课程设计好帮手:Phi-4-mini-reasoning辅助ER图设计与SQL优化
数据库课程设计好帮手:Phi-4-mini-reasoning辅助ER图设计与SQL优化 1. 课程设计的痛点与解决方案 每到学期末,计算机专业的学生们都会面临一个共同的挑战——数据库课程设计。这个需要完成ER图设计、SQL编写和文档撰写的综合项目,常常让初学…...
远程协助工具
# 详见:https://mp.weixin.qq.com/s/sY-KrOqpY3C1JUeiELEJNw # 来源:https://chat.qwen.ai/# ToDesk https://www.todesk.com/# 向日葵 https://sunlogin.oray.com/# TeamViewer https://www.teamviewer.com/# AnyDesk https://anydesk.com/ https://any…...
Go Module 依赖冲突调试方法
Go Module 依赖冲突调试方法 在Go语言开发中,依赖管理是一个关键环节。随着项目规模的扩大,依赖的第三方库越来越多,版本冲突问题也愈发常见。Go Module作为官方推荐的依赖管理工具,虽然简化了依赖管理流程,但在多级依…...
Qwen3.5-2B图文理解教程:GIF动图逐帧理解+动态内容总结生成方法
Qwen3.5-2B图文理解教程:GIF动图逐帧理解动态内容总结生成方法 1. 引言 Qwen3.5-2B是一款轻量化多模态基础模型,属于Qwen3.5系列的小参数版本(20亿参数)。这款模型主打低功耗、低门槛部署,特别适配端侧和边缘设备&am…...
YOLO-v8.3实战:用AI识别图片中的物体,5分钟完成你的第一个检测项目
YOLO-v8.3实战:用AI识别图片中的物体,5分钟完成你的第一个检测项目 你是否曾经好奇,那些能自动识别照片中物体的人工智能是如何工作的?想象一下,你拍了一张街景照片,AI不仅能告诉你照片里有汽车、行人和红…...
Phi-4-mini-reasoning案例分享:用逻辑题测试模型对‘必要条件’的理解深度
Phi-4-mini-reasoning案例分享:用逻辑题测试模型对必要条件的理解深度 1. 模型能力定位 Phi-4-mini-reasoning是专为推理任务优化的文本生成模型,其核心优势在于处理需要多步逻辑推导的问题。与通用对话模型不同,它更擅长处理以下类型任务&…...
CentOS部署PHP项目完整步骤
CentOS 7.9 部署 PHP 7.4 MySQL 5.7.44 完整步骤 由于 CentOS 7 已于 2024 年 6 月 30 日停止官方维护,原有的 yum 源已不可用,因此必须首先更换为阿里云镜像源才能正常安装软件。 一、系统环境准备 1.1 更换阿里云 YUM 源 # 1. 备份原有源 mv /etc/yum…...
