java并发编程专题(六)----浅析(JUC)Semaphore
作者:rickiyang 发布时间:2023-07-27 23:30:28
半路开始看的朋友可以回顾一下前几篇
java并发编程专题(一)----线程基础知识
java并发编程专题(二)----如何创建并运行java线程
java并发编程专题(三)----详解线程的同步
java并发编程专题(四)----浅谈(JUC)Lock锁
java并发编程专题(五)----详解(JUC)ReentrantLock
Semaphore,从字面意义上我们知道他是信号量的意思。在java中,一个计数信号量维护了一个许可集。Semaphore 只对可用许可的号码进行计数,并采取相应的行动。拿到信号量的线程可以进入代码,否则就等待。通过acquire()和release()获取和释放访问许可。
信号量Semaphore是一个控制访问多个共享资源的计数器,它本质上是一个“共享锁”。
Java并发提供了两种加锁模式:共享锁和独占锁。前面介绍的ReentrantLock就是独占锁。对于独占锁而言,它每次只能有一个线程持有,而共享锁则不同,它允许多个线程并行持有锁,并发访问共享资源。
独占锁它所采用的是一种悲观的加锁策略, 对于写而言为了避免冲突独占是必须的,但是对于读就没有必要了,因为它不会影响数据的一致性。如果某个只读线程获取独占锁,则其他读线程都只能等待了,这种情况下就限制了不必要的并发性,降低了吞吐量。而共享锁则不同,它放宽了加锁的条件,采用了乐观锁机制,它是允许多个读线程同时访问同一个共享资源的。
举一个生活中的例子,有一条单行道路口有一红绿灯在正常的绿灯时间内如果骑车速度都很平均只能过去20辆车,这就意味着排在前面的20辆肯定能过去红绿灯,后面的就只能等下一个绿灯了。但是如果这个时候有车不想过去这个路口它驶向了边上别的路,那么后面的车就有机会。下面我们来看一个简单的例子:
public class TestSemaphore {
public static void main(String[] args) {
final Semaphore semaphore = new Semaphore(5);
ExecutorService executorService = Executors.newCachedThreadPool();
for(int i = 0;i<10;i++){
int j = 0;
executorService.submit(new A("car"+(j++),semaphore),"Thread"+(j++));
//new Thread(new A("car"+(j++),semaphore),"Thread"+(j++)).start();
if(i == 5){
try {
Thread.sleep(1000);
System.out.println("最后还有"+semaphore.availablePermits()+"个许可可用");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("最后还有"+semaphore.availablePermits()+"个许可可用");
}
}
class A implements Runnable{
String carName;
private Semaphore semaphore;
public A(String carName, Semaphore semaphore){
this.carName = carName;
this.semaphore = semaphore;
}
public void getWay(){
System.out.println("this car is get the way" + Thread.currentThread().getName());
}
public void run() {
try {
if(semaphore.availablePermits() > 0){
semaphore.acquire();
getWay();
semaphore.release();
}else{
System.out.println("请等待========");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
来源:https://www.cnblogs.com/rickiyang/p/11074264.html
猜你喜欢
- 在使用springMVC框架构建web应用,客户端常会请求字符串、整型、json等格式的数据,通常使用@ResponseBody注解使 co
- Console.WriteLine("This is a Client, host name is {0}", Dns.
- 要想实现android手机通过扫描名片,得到名片信息,可以使用脉可寻提供的第三方SDK,即Maketion ScanCard SDK,脉可寻
- 在导入studio工程的时候,进行sync的时候,提示Error:Configuration with name 'default&
- 首先给出一段代码:public class AslistMethod { public static void main(String[]
- 本文介绍了Spring Boot Admin监控服务上下线邮件通知,分享给大家,具体如下:微服务架构下,服务的数量少则几十,多则上百,对服务
- 这里使用的是dynamic-datasource-spring-boot-starter ,它是一个基于springboot的快速集成多数据
- forward_list 概述forward_list 是 C++ 11 新增的容器,它的实现为单链表。forward_list 是支持从容
- 本文介绍了Flutter 通过Clipper实现各种自定义形状的示例代码,分享给大家,具体如下:ClipOval 圆形裁剪ClipOval(
- using System; using System.Collections.Generic; using System.Text; usi
- 只能输入数字:"^[0-9]*$"。只能输入n位的数字:"^\d{n}$"。只能输入至少n位的数字:
- 先上图下拉刷新跟原生开发一样,下拉刷新在flutter里提供的有组件实现 RefreshIndicator一直不明白为啥组件中都提供下拉刷新
- [LeetCode] 9. Palindrome Number 验证回文数字Determine whether an integer is
- 您已经看到很多包含视频内容的应用程序,比如带有视频教程的食谱应用程序、电影应用程序和体育相关的应用程序。您是否想知道如何将视频内容添加到您的
- 一、导航栏UINavigationBar1、导航栏的使用在iOS开发中,我们通常会使用导航控制器,导航控制器中封装了一个UINavigati
- 一、导入和导出导入:通过解析excel表格中的数据,然后将数据放到一个集合中,接着通过对持久层操作,将数据插入到数据库中,再加载一下页面,从
- 引言在高并发的场景下,异步是一个极其重要的优化方向。前段时间,生产环境发生一次事故,笔者认为事故的场景非常具备典型性 。写这篇文章,笔者想和
- 这篇文章主要介绍了spring boot如何实现切割分片上传,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需
- 简介Android给我们提供了一种轻量级的异步任务类AsyncTask。该类中实现异步操作,并提供接口反馈当前异步执行结果及进度,这些接口中
- 如果有哪一个做程序员的小伙伴说自己没有遇到中文乱码问题,我是不愿意相信的。今天在做微信订阅号的智能回复时,又一时迷乱的跳进了中文乱码这个火坑