从Redisson的RedissonSemaphore引发的信号量实际含义的思考

news/2024/9/18 8:16:44/

Semaphore到底该如何使用

事情的起因是最近在看redisson的源码,刚好看到了RedissonSemaphore的acquire/release实现。

public RFuture<Void> releaseAsync(int permits) {if (permits < 0) {throw new IllegalArgumentException("Permits amount can't be negative");}if (permits == 0) {return new CompletableFutureWrapper<>((Void) null);}RFuture<Void> future = commandExecutor.syncedEval(getRawName(), StringCodec.INSTANCE, RedisCommands.EVAL_VOID,"local value = redis.call('incrby', KEYS[1], ARGV[1]); " +"redis.call('publish', KEYS[2], value); ",Arrays.asList(getRawName(), getChannelName()), permits);if (log.isDebugEnabled()) {future.thenAccept(o -> {log.debug("released, permits: {}, name: {}", permits, getName());});}return future;}

这段代码并没有去校验key是否存在,以及设置的semaphore的最大值是多少,直接进行了incr操作。
如果其他客户端存在重复release()的行为,就会导致凭证超发的情况发生。

因此回过头去看了一下jdk的semaphore的实现。

Semaphore semaphore = new Semaphore(1);semaphore.acquire();semaphore.release();semaphore.release();semaphore.release();semaphore.release();boolean b1 = semaphore.tryAcquire();boolean b2 = semaphore.tryAcquire();boolean b3 = semaphore.tryAcquire();System.out.println(b1 + ":" + b2 + ":" + b3);

这段代码的执行结果是:true:true:true

JDK的semaphore的release()核心代码如下:

 protected final boolean tryReleaseShared(int releases) {for (;;) {int current = getState();int next = current + releases;if (next < current) // overflowthrow new Error("Maximum permit count exceeded");if (compareAndSetState(current, next))return true;}}

这里只是在release的时候,将当前current和next的值做比对,防止并发情况下修改值异常问题,并不会去校验new Semaphore()时传入的初始化值。其中getState()返回的就是初始化时的state。

    protected final int getState() {return state;}

在tryReleaseShared()方法的compareAndSetState(current, next)中,会修改这个state的值。
在这里插入图片描述
在这里插入图片描述
所以在JDK的semaphore实现中,new Semaphore(int permits)传入的值,只是一个初始化的值,如果在实际使用的时候,进行了重复release()释放,就会导致多余的凭证超发的问题。

在了解了JDK的semaphore的实际实现后,就不难理解redisson的RedissonSemaphore实现了,是完全与JDK保持一致的。

在JDK的semaphore使用时,需要保证多线程进行凭证释放的时候,不会重复release(),防止凭证超发,而使用RedissonSemaphore的时候,一般是分布式的场景,所以常见的凭证超发的情况可能就在于重复消费,所以需要调用方自己保证调用幂等,避免凭证超发。


http://www.ppmy.cn/news/87764.html

相关文章

为什么都在学python?

自然是因为Python简单易学且应用领域广&#xff01; Python近段时间一直涨势迅猛&#xff0c;在各大编程排行榜中崭露头角&#xff0c;得益于它多功能性和简单易上手的特性&#xff0c;让它可以在很多不同的工作中发挥重大作用。 正因如此&#xff0c;目前几乎所有大中型互联…

vite-plugin-pwa配置详解

vite-plugin-pwa配置详解 前提&#xff1a;前端域名和后端服务域名相同时&#xff0c;用window.open新开页面下载或者导出文件&#xff0c;项目中导出和下载功能失效&#xff0c;原因是&#xff0c;域名相同走缓存 实现service worker离线缓存以前需要自己编写sw.js文件内容&…

Worker及XMLHttpRequest简单使用说明

Worker 一、作用及使用场景 在Web应用程序中创建多线程环境&#xff0c;可以运行独立于主线程的脚本&#xff0c;从而提高Web应用的性能和响应速度。 Worker.js主要应用场景包括&#xff1a; 数据处理&#xff1a;在数据量较大的情况下&#xff0c;使用Worker可以将数据分成…

抖音seo源码开发,开源技术保姆式搭建

抖音seo源码优化逻辑 抖音SEO是通过一系列的技术手段和优化策略来提升视频内容在抖音平台内的曝光率和排名。其中主要包括以下几个方面&#xff1a; 1.关键词优化。通过对视频的标题、描述等元素的关键词进行优化&#xff0c;提高相关性和匹配度&#xff0c;让用户更容易搜索到…

Java split()方法中的特殊符号

一、split是什么&#xff1f; 在Java中&#xff0c;split()方法用于分隔字符串&#xff0c;可以根据匹配给定的正则表达式来拆分字符串。split()方法可以将一个字符串分割为子字符串&#xff0c;然后将结果作为字符串数组返回&#xff1b;语法如下&#xff0c;其中参数regex指…

【SpringCloud】三、Nacos服务注册+配置管理+集群搭建

文章目录 一、认识Nacos1、安装2、服务注册和发现3、服务分级存储模型4、负载均衡策略--NacosRule5、服务实例的权重设置5、环境隔离namespace6、Eureka和Nacos的区别 二、Nacos配置管理1、统一配置管理2、微服务配置拉取3、配置热更新4、多环境配置共享 三、Nacos集群搭建1、初…

【2023年电工杯数学建模竞赛】选题分析+A题B题完整思路+代码分享

思路和代码会第一时间分享出来&#xff0c;可以先关注博主 1.竞赛介绍 2.本次大赛选题分析 首先大家要清楚获奖只和比例有关&#xff0c;和具体题目关系不大&#xff0c;不会出现选难题就比简单题获奖率高很多的情况出现&#xff0c;这是一个选拔性质的比赛是按照比例来的 2…

如何声明和初始化变量?

在Java中&#xff0c;声明和初始化变量可以通过以下方式进行&#xff1a; 声明变量并赋初值&#xff1a; javaCopy code dataType variableName initialValue; 其中&#xff0c;dataType是变量的数据类型&#xff0c;variableName是变量名&#xff0c;initialValue是变量的初…

操作系统第四章——文件管理(下)

竹本无心&#xff0c;却节外生枝&#xff0c;藕却有孔&#xff0c;但出淤泥而不染&#xff0c;人生如梦&#xff0c;却却不随人愿&#xff0c;万般皆是命&#xff0c;半点不由人 文章目录 4.1.5 逻辑结构VS物理结构4.1.6 文件的基本操作知识总览创建文件删除文件打开文件关闭文…

自古以来,反射也是兵家必争之地

成文耗时1小时&#xff0c;阅读5min&#xff0c;有用指数5颗星。 这几天收到一个战术性需求&#xff0c;将一大坨字段序列化为特定格式的字符串。 大概是下表&#xff1a; 序号字段名描述是否必填0logVersion日志版本是1productName产品是2serviceName服务是.........25extend3…

burpsuite导入网站的客户端证书

0x01 背景 个别网站需要导入客户端的XX.P12证书&#xff0c;如果没有导入直接访问网站&#xff0c;浏览器会提示&#xff1a;400 Bad Request , 出现&#xff1a;No required SSL certificate was sent等提示&#xff0c;如下图 此时需要在burpsuite中导入证书 0x02 网站客户…

基于SpringBoot+Uniapp的球队周边微信小程序

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 随着微信小程序的兴起…

企业级实战 Spring Boot + K8S 中的滚动发布、优雅停机、弹性伸缩、应用监控、配置分离

下面为大家介绍我司生产环境使用了3年的基于K8S的dev ops 配置实现 K8s SpringCloud实现零宕机发版&#xff0c;优雅重启&#xff1a;健康检查滚动更新优雅停机弹性伸缩Prometheus监控配置分离&#xff08;镜像复用&#xff09; 汇总配置 业务层面 项目依赖 pom.xml 使用 s…

版图设计IC617 virtuoso启动以及smic18mmrf加载库

一. 启动virtuoso 1.1 创建一个目录用于库管理 mkdir pro3 1.2 拷贝.bashrc到工程目录下&#xff0c;.bashrc存在~目录下&#xff0c;是一个隐藏文件&#xff0c;需要用ls -la查看 1.3 执行.bashrc文件 1.4 启动 virtuoso & 1.5 检查库中是否包含系统基本库&#xff0c;如…

python 生成器

生成器 Python生成器是一种特殊的函数,它可以在需要时生成一系列值,而不是一次性生成所有值。生成器使用yield关键字来暂停函数的执行,并返回一个值。当函数再次被调用时,它将从yield语句停止的地方继续执行。所以生成器非常适合处理大量数据或无限序列。 生成器…

【TI毫米波雷达笔记】IWR6843AOPEVM-G的DCA1000EVM模式配置及避坑

【TI毫米波雷达笔记】IWR6843AOPEVM-G的DCA1000EVM模式配置及避坑 IWR6843AOPEVM-G版本可以直接与DCA1000EVM连接 进行数据获取 不需要连接MMWAVEICBOOST版 直接使用 DCA1000mmWave Studio 软件进行数据采集 在官方手册中 User’s Guide 60GHz 毫米波传感器EVM 有相关模式的开…

滤镜美颜sdk的实现方式和工作流程:从技术层面了解美颜算法

众所周知&#xff0c;实现美颜功能的核心技术之一就是滤镜美颜sdk。在本文中&#xff0c;我们将从技术层面来探讨滤镜美颜sdk的实现方式和工作流程&#xff0c;帮助读者更深入了解美颜算法。 一、美颜算法的基本原理 美颜算法的基本原理是通过图像处理技术&#xff0c;对人物…

MyBatisPlus快速入门(二)MyBatisPlus快速入门体验

一、初始化数据库&#xff08;基于 HeidiSQL&#xff09;1.1 创建数据库1.2创建数据表1.3 初始化数据 二、初始化项目&#xff08;基于Spring Boot&#xff09;2.1 创建项目2.2 新增依赖2.3 数据库配置2.4 配置 MyBatis Plus2.5 创建实体类2.6 创建Mapper层接口2.7 创建Server层…

AI技术将手语翻译带入新阶段

对于无声者来说&#xff0c;手语可能就是对外交流的唯一方法&#xff0c;但是随着AI技术的进步&#xff0c;可能会让无声者有更多的选择与和外界进行交流。 近日在巴塞罗那超级计算中心(BSC)和加泰罗尼亚理工大学(UPC)携手合作取得了重大突破&#xff0c;他们成功开发出一项全…

微信小程序 基础模板引入sass的两种方法

推荐使用第二种方法 一、VSCode扩展引入&#xff08;旧&#xff09; 1.vscode搜索扩展 Easy Sass安装 2.微信开发者工具导入vscode安装的所有扩展 3.修改sass扩展配置 打开扩展目录 找到刚导入的sass扩展 打开package.json文件 改成这样 保存 4.重新打开此项目 配置完事 5.使…