首页 文章 精选 留言 我的

精选列表

搜索[跨平台工具],共10000篇文章
优秀的个人博客,低调大师

Java多线程并发控制工具信号量Semaphore,实现原理及案例

信号量(Semaphore)是Java多线程兵法中的一种JDK内置同步器,通过它可以实现多线程对公共资源的并发访问控制。一个线程在进入公共资源时需要先获取一个许可,如果获取不到许可则要等待其它线程释放许可,每个线程在离开公共资源时都会释放许可。其实可以将Semaphore看成一个计数器,当计数器的值小于许可最大值时,所有调用acquire方法的线程都可以得到一个许可从而往下执行。而调用release方法则可以让计数器的值减一。 信号量的主要应用场景是控制最多N个线程同时地访问资源,其中计数器的最大值即是许可的最大值N。以停车场为例,假设停车场一共有8个车位,其中6个车位已被停放,然后来了两辆汽车,此时因为刚好剩下两个车位所以这两辆车都能停放。接着又来了一辆车,现在已经没有空位了所以只能等待其它车离开。此时刚好一辆红色汽车离开停车场,来开后黄车刚好可以停进去,假如又有一辆汽车进来则该车又得等待。如此往复。这个过程中停车场就是公共资源,车位数就是信号量最大许可数,车辆就好比线程。 四要素 信号量的四要素为:最大许可数、公平模式、acquire方法以及release方法。最大许可数和公平模式在构建Semaphore对象时指定,分别表示公共资源最多可以多少个线程同时访问以及获取许可时是否使用公平模式。acquire方法用于获取许可,假如因为不足许可的话则进入等待状态。release方法用于释放许可。 非公平模式的实现 Semaphore类的实现是基于AQS同步器来实现的,不管是公平模式还是非公平模式都是基于AQS的共享模式,只是在获取许可的操作逻辑有差异。Semaphore的默认模式为非公平模式,我们先看非公平模式的实现。  Semaphore类的几个主要方法如下所示,其中提供了两个构造函数,相关的两个参数为许可最大数和是否使用公平模式,其中FairSync是公平模式的同步器而NonfairSync则是非公平模式的同步器。有两个acquire方法,无参时默认是一次获取1个许可,而如果传入整型参数则表示一次获取若干个许可。对应地,也有两个release方法,无参时表示释放1个许可,而整型参数则表示一次释放若干个许可。Semaphore主要的几个方法如下 Semaphore内部的Syn子类是公平模式FairSync类和非公平模式NonfairSync类的抽象父类,许可最大数与AQS同步器的状态变量对应。因为模式是非公平模式,所以这里提供了非公平的许可获取方法nonfairTryAcquireShared。非公平模式其实就是在许可数量允许的情况下,让所有线程都进行自旋操作,而不管它们先来后到的顺序,全部线程放到一起去竞争许可。其中compareAndSetState方法提供了CAS算法从而能够保证并发修改许可值,而剩余许可数等于当前可用许可值减去当前消耗许可数,需要注意的是当剩余许可数小于0时则返回负数从而导致线程会进入等待队列中。tryReleaseShared方法则提供了释放许可的操作,不管是不是公平模式都使用该方法即可,释放许可的逻辑是相同的。通过自旋操作来将释放的许可数增加到当前剩余许可数。 非公平模式NonfairSync类的实现主要是tryAcquireShared方法,直接调用父类Sync的的nonfairTryAcquireShared方法即可。  公平模式实现 公平模式与非公平模式的主要差异就在获取许可时的机制,非公平模式直接通过自旋操作让所有线程竞争许可,从而导致了非公平。而公平模式则通过队列来实现公平机制。它们的差异就在tryAcquireShared方法,我们看公平模式的tryAcquireShared方法。实际上不同的地方就在下图中加了方框的两行代码,它会检查是否已经存在等待队列,如果已经有等待队列则返回-1,返回-1则表示让AQS同步器将当前线程进入等待队列中,队列则意味着公平。实际上,这也并非是严格的公平,在前面讲到的AQS同步器的公平性章节有深入讲过AQS的公平性,如果忘记了可以重新查阅加深理解。而且在为达到最大许可数的情况下,所有线程也并没有进入等待队列中,而是全部线程进行自旋获取许可。 案例 1 我们先看一个简单的例子,首先实例化一个拥有5个许可的信号量对象,然后一共有10个线程一同尝试获取5个许可,得到许可的线程将value进行累加1,接着睡眠五秒,最后释放许可。 以上程序输出如下,其中有五个线程输出“counting number : xx”后其他线程则开始等待。大概等待5秒后获得许可的五个线程执行释放许可操作,然后其它线程才能获得许可并往下执行。 案例 2 例子二与例子一很相似,不同的地方在于每次获取许可时会消耗2个许可,同样释放时也释放2个许可。这里实例化一个拥有6个许可的信号量对象,然后10个线程一同尝试获取许可。但这次最多只能同时3个线程得到许可,也就是三个线程得到许可后对value值进行累加1,然后睡眠5秒后释放许可。接着另外三个线程又获得许可往下执行,直到10个线程都执行完。 总结 本文介绍了一个JDK内置的同步器——信号量(Semaphore),通过它能够控制最多若干个线程访问公共资源。它可以看成是一个计数器,当计数器的值小于许可最大值时线程能够往下执行,反之线程则只能等待。我们深入分析了Semaphore的实现原理,它基于AQS同步器进行实现且提供了公平和非公平两种模式,并且我们对这两种模式的实现分别进行了分析。通过本文我们已经能够很深入清晰理解Semaphore的原理机制了。

优秀的个人博客,低调大师

PowerToys v0.21.1 发布,微软开发的免费实用工具集

PowerToys v0.21.1现已发布,具体更新内容如下: PT Run: 删除了 action keywords 中对空格的需求。这意味着用户现在可以输入>ipconfig 图标缓存已修复,现在带有彩色图标 通过 ClearType 改进了字体渲染 Result速度提高 支持 URLs 修正错误,包括计算错误 FancyZone: Win+Arrow key 是基于区域矩形的方向 修正错误 Runner: 修复了从非管理员帐户提升的 Toast 通知 Shortcut Guide: 改进了 vkey 捕获功能,可以解决某些用例无法显示的问题 SVG in File Explorer: 嵌入式图像标签现在将在资源管理器中呈现 Color Picker: 修复了通过 false positive keystrokes 启动的错误 Accessibility: Settings、PT Run 和 KBM正在进行改进 Localization: Pipeline 现已设置完毕,即将在所有实用程序上进行完整的 E2E 传递。 Dev quality of life improvements: 继续减少警告计数。此版本已删除〜80条 启用了 StyleCop 的E2E 在 E2E 中开始添加 FxCop 更新说明:https://github.com/microsoft/PowerToys/releases/tag/v0.21.1

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册