您现在的位置是:亿华云 > 应用开发
别再和面试官说不懂信号量Semaphore了!
亿华云2025-10-03 22:30:13【应用开发】7人已围观
简介已经习惯了阿里面试官的冷笑:用过Semaphore吧,不妨说说?本质就是 信号量模型,模型图如下:其中的 计数器 和 等待队列 对外部是透明的,仅能通过提供的三大方法访问它们。详细说说哪三大方法?in
已经习惯了阿里面试官的别再冷笑:用过Semaphore吧,不妨说说?和面号量
本质就是 信号量模型,模型图如下:
其中的试官说 计数器 和 等待队列 对外部是透明的,仅能通过提供的懂信三大方法访问它们。
详细说说哪三大方法?别再
init()用于设置计数器的初始值。
down()计数器-1。和面号量若此时计数器<0,试官说则当前线程被 阻塞。懂信
up()计数器+1。别再若此时计数器≤0,和面号量则唤醒 等待队列 中的试官说一个线程,并将其从【等待队列】移除。懂信有同学可能会认为这里的别再判断条件应该≥0,估计你是和面号量理解成生产者-消费者模式中的生产者了。可以反过来想,试官说>0 意味着没有阻塞的线程,所以只有 ≤0 时才需要唤醒一个等待的线程。
down()、up()应配对使用,并按序使用:
先调用down(),获取锁 执行处理完后,网站模板调用up(),释放锁若信号量init值为1,并发场景下应该不会出现>0情况,除非故意调先用up(),但这也失去了信号量的意义。
注意,这些方法都是原子性的,由信号量模型的实现方保证。JDK里的信号量模型就是由Semaphore实现,Semaphore保证了这三个方法都是原子操作。
talk is cheap,show me code?信号量模型中的down()、up()最早被称为P操作和V操作,信号量模型也称PV原语。还有的人会用semWait()和semSignal()表达它们,叫法不同,语义都相同。JUC的acquire()、release()分别对应down()和up()。
如何使用信号量?
就像信号灯,必须先检查是否为绿灯才能通过。比如累加器,亿华云count+=1操作是个临界区,只允许一个线程执行,也就是说要保证互斥。
假设线程t1、t2同时访问add(),当同时调用acquire时,由于acquire是个原子操作,仅会有一个线程(假设t1)把信号量里的计数器减为0,t2则是将计数器减为-1:
对t1,信号量里面的计数器的值是0,≥0,所以t1不会被阻塞,而是继续执行 对t2,信号量里面的计数器的值是-1,<0,所以t2被阻塞所以此时只有t1会进入临界区执行count+=1。
当t1执行release(),信号量里计数器的值是-1,加1之后的源码下载值是0,≤0,根据up(),此时等待队列中的t2会被唤醒。于是t2在t1执行完临界区代码后,才获得进入临界区执行的机会,这就保证了互斥。
既然有JDK提供了Lock,为啥还要提供一个Semaphore ?
实现互斥锁,仅是 Semaphore的部分功能,Semaphore还可以允许多个线程访问一个临界区。
最常见的就是各种池化资源,比如数据库连接池,同一时刻,允许多个线程同时使用连接池。每个连接在被释放前,不允许其他线程使用。
对象池要求一次性创建出N个对象,之后所有的线程重复利用这N个对象,当然对象在被释放前,也是不允许其他线程使用的。所以核心就是限流器,这里的限流指不允许多于N个线程同时进入临界区。
如何快速实现一个这样的限流器呢?
那就是信号量。把计数器的值设置成对象池里对象的个数N即可:
注意这里使用的是 Vector,进入临界区的N个线程不安全。add/remove都是不安全的。比如 ArrayList remove() :
好的,请回家等通知吧!
本文转载自微信公众号「JavaEdge」,可以通过以下二维码关注。转载本文请联系JavaEdge公众号。
很赞哦!(48148)
相关文章
- 4、选择一个安全的域名注册商进行域名注册
- 小学生们在B站讲算法,网友:我只会阿巴阿巴
- 项目复盘:通过动态脚本,实现按需加载语言包
- Hadoop伪分布式搭建操作步骤指南
- 3.dns修改成功后,点击“域名解析”,按提示进行操作。解析格式一般如下:
- 如何提升代码质量
- 关于SQL注入的一些技巧分享
- 纯 CSS 实现三角形的三种方式
- 3、不明先知,根据相关征兆预测可能发生的事件,以便提前做好准备,赶紧注册相关域名。;不差钱域名;buchaqian抢先注册,就是这种敏感类型。预言是最敏感的状态。其次,你应该有眼力。所谓眼力,就是善于从社会上时不时出现的各种热点事件中获取与事件相关的域名资源。眼力的前提是对域名领域的熟悉和丰富的知识。
- 外媒速递:AWS生产环境下十大MongoDB部署最佳实践