温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

什么是信号量Semaphore

发布时间:2021-09-17 11:22:54 来源:亿速云 阅读:85 作者:柒染 栏目:web开发

这篇文章将为大家详细讲解有关什么是信号量Semaphore,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

什么是信号量Semaphore

本质就是 信号量模型,模型图如下:

其中的 计数器 和 等待队列 对外部是透明的,仅能通过提供的三大方法访问它们。

什么是信号量Semaphore

详细说说哪三大方法?

  • init()

用于设置计数器的初始值。

  • down()

计数器-1。若此时计数器<0,则当前线程被 阻塞。

  • up()

计数器+1。若此时计数器&le;0,则唤醒 等待队列  中的一个线程,并将其从【等待队列】移除。有同学可能会认为这里的判断条件应该&ge;0,估计你是理解成生产者-消费者模式中的生产者了。可以反过来想,>0  意味着没有阻塞的线程,所以只有 &le;0 时才需要唤醒一个等待的线程。

down()、up()应配对使用,并按序使用:

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. 先调用down(),获取锁

  3. 执行处理完后,调用up(),释放锁

若信号量init值为1,并发场景下应该不会出现>0情况,除非故意调先用up(),但这也失去了信号量的意义。

注意,这些方法都是原子性的,由信号量模型的实现方保证。JDK里的信号量模型就是由Semaphore实现,Semaphore保证了这三个方法都是原子操作。

talk is cheap,show me code?

什么是信号量Semaphore

信号量模型中的down()、up()最早被称为P操作和V操作,信号量模型也称PV原语。还有的人会用semWait()和semSignal()表达它们,叫法不同,语义都相同。JUC的acquire()、release()分别对应down()和up()。

如何使用信号量?

就像信号灯,必须先检查是否为绿灯才能通过。比如累加器,count+=1操作是个临界区,只允许一个线程执行,也就是说要保证互斥。

什么是信号量Semaphore

假设线程t1、t2同时访问add(),当同时调用acquire时,由于acquire是个原子操作,仅会有一个线程(假设t1)把信号量里的计数器减为0,t2则是将计数器减为-1:

  • 对t1,信号量里面的计数器的值是0,&ge;0,所以t1不会被阻塞,而是继续执行

  • 对t2,信号量里面的计数器的值是-1,<0,所以t2被阻塞

所以此时只有t1会进入临界区执行count+=1。

当t1执行release(),信号量里计数器的值是-1,加1之后的值是0,&le;0,根据up(),此时等待队列中的t2会被唤醒。于是t2在t1执行完临界区代码后,才获得进入临界区执行的机会,这就保证了互斥。

既然有JDK提供了Lock,为啥还要提供一个Semaphore ?

实现互斥锁,仅是 Semaphore的部分功能,Semaphore还可以允许多个线程访问一个临界区。

最常见的就是各种池化资源,比如数据库连接池,同一时刻,允许多个线程同时使用连接池。每个连接在被释放前,不允许其他线程使用。

对象池要求一次性创建出N个对象,之后所有的线程重复利用这N个对象,当然对象在被释放前,也是不允许其他线程使用的。所以核心就是限流器,这里的限流指不允许多于N个线程同时进入临界区。

如何快速实现一个这样的限流器呢?

那就是信号量。把计数器的值设置成对象池里对象的个数N即可:

什么是信号量Semaphore

注意这里使用的是 Vector,进入临界区的N个线程不安全。add/remove都是不安全的。比如 ArrayList remove() :

什么是信号量Semaphore

关于什么是信号量Semaphore就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI