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…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...

docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...

label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...

图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...