动力节点首页 全国咨询热线:400-8080-105

绑定手机号,登录
手机号

验证码

微信登录
手机号登录
手机号

验证码

微信登录与注册
微信扫码登录与注册

扫码关注微信公众号完成登录与注册
手机号登录
首页 > 文章

浅谈多线程中的信号量

05-24 14:24 925浏览
举报 T字号
  • 大字
  • 中字
  • 小字

信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。

信号量可以分为几类:

  • 二进制信号量(binary semaphore) / 二元信号量 :只允许信号量取0或1值,,只有两种状态:占用与非占用,其同时只能被一个线程获取。
  • 整型信号量(integer semaphore):信号量取值是整数,它可以被多个线程同时获得,直到信号量的值变为0。
  • 记录型信号量(record semaphore):每个信号量s除一个整数值value(计数)外,还有一个等待队列List,其中是阻塞在该信号量的各个线程的标识。当信号量被释放一个,值被加一后,系统自动从等待队列中唤醒一个等待中的线程,让其获得信号量,同时信号量再减一。
  • 信号量通过一个计数器控制对共享资源的访问,信号量的值是一个非负整数,所有通过它的线程都会将该整数减一。如果计数器大于0,则访问被允许,计数器减1;如果为0,则访问被禁止,所有试图通过它的线程都将处于等待状态。
  • 二元信号量相当于互斥锁,也就是说当信号量初值为1时,wait相当于lock,signal相当于unlock。而它允许在一个线程加锁在另任一线程解锁,使用更加灵活,而带来的不确定性则相应增加。

下述代码中,线程A将等线程B调用之后再逐一运行。如果换成NSLock理论上由其他线程是不允许的,但运行结果一切正常。而换成NSRecursiveLock递归锁,所有加锁操作将失效,线程不会挂起。用pthread_mutex,也是在设置属性为可递归时,加锁才会失效。(普通互斥锁可能是由信号量实现的,具体原因不明,但不建议这样使用。)

let semt = DispatchSemaphore(value: 1)
let q1 = DispatchQueue(label:"A")
let q2 = DispatchQueue(label:"B")
for i in 0...20 {
   q1.async {
        print(" \(i)")
        semt.wait()
        print("waite \(i)")
    }
    q2.asyncAfter(deadline: .now() + .seconds(i * 1)){
        semt.signal()
        print("post \(i) ")
    }
}
  • 控制某个代码块的最大并发数。通过设置信号量的初值,很容易实现某一段代码片段的执行的并发数。或者说控制某个资源最大同时访问量。
  • 当信号量的值为0,而waite/signal分属不同线程时,可以适用于经典的生产者-消费者模型。即一种一对一的观测监听方式。当生产者完成生产后,立刻通知消费者购买。而没有产品时,消费者只能等待。

抽象的来讲,信号量是一个非负整数(车位数),所有通过它的线程/进程(车辆)都会将该整数减一(通过它当然是为了使用资源),当该整数值为零时,所有试图通过它的线程都将处于等待状态。只要我们能够抓住信号量的本质,理解起来也就简单许多了。类似的不常见的多线程术语,在动力节点在线的视频课程中都有专门的讲解,让我们打好Java基础的同时,拓展自己的知识面,开拓自己的视野。

0人推荐
共同学习,写下你的评论
0条评论
代码小兵652
程序员代码小兵652

113篇文章贡献392215字

相关课程 更多>

作者相关文章更多>

推荐相关文章更多>

Java面试题及答案整理

提枪策马乘胜追击04-21 20:01

Spring常见面试题

代码小兵92504-17 16:07

Java零基础实战项目——五子棋

代码小兵98804-25 13:57

Java string类详解

杨晶珍05-11 14:54

6道经典算法面试题

杨晶珍05-12 16:39

发评论

举报

0/150

取消