1.信号量介绍
// 创建信号, 信号计数为2
// value 一般控制任务最大并发数, 此时允许执行2个任务
let sem = DispatchSemaphore(value: 2)
// 等待, 信号计数减一
sem.wait()
// 释放信号, 信号计数加一
sem.signal()
2.信号量应用
2.1信号量控制任务并发数, 通过设置信号计数
let sem = DispatchSemaphore(value: 2)
// 并发队列
let queue = DispatchQueue(label: "", qos: .default, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
// 添加任务
queue.async {
sem.wait()
print("1")
sleep(2)
sem.signal()
}
queue.async {
sem.wait()
print("2")
sleep(2)
sem.signal()
}
queue.async {
sem.wait()
print("3")
sleep(2)
sem.signal()
}
queue.async {
sem.wait()
print("4")
sleep(2)
sem.signal()
}
// 执行结果 2个2个打印 例如 1 2 , 4 3
2.2信号量监听所有任务完成
let sem = DispatchSemaphore(value: 2)
// 并发队列
let queue = DispatchQueue(label: "", qos: .default, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
// 添加任务
queue.async {
print("1")
sleep(2)
print("done")
sem.signal()
}
queue.async {
print("2")
sleep(2)
print("done")
sem.signal()
}
queue.async {
print("3")
sleep(2)
print("done")
sem.signal()
}
queue.async {
print("4")
sleep(2)
print("done")
sem.signal()
}
// 此处监听
queue.sync {
sem.wait()
sem.wait()
sem.wait()
sem.wait()
print("all done")
}
2.3信号量加锁, 设置信号计数为0
let sem = DispatchSemaphore(value: 0)
let queue = DispatchQueue(label: "", qos: .default, attributes: .concurrent, autoreleaseFrequency: .inherit, target: nil)
queue.async {
print("1")
sleep(2)
sem.signal()
}
queue.async {
sem.wait()
print("2")
sleep(2)
}
3.信号量原理
-
dispatch_semaphore_wait
信号量等待,内部是对并发数做自减操作,如果为 小于0,会执行_dispatch_semaphore_wait_slow
然后调用_dispatch_sema4_wait
是一个do-while
,知道满足条件结束循环
-
dispatch_semaphore_signal
信号量释放 ,内部是对并发数做自加操作,直到大于0时,为可操作
- 保持线程同步,将异步执行任务转换为同步执行任务
- 保证线程安全,为线程加锁,相当于
自旋锁
4.参考文章
https://www.jianshu.com/p/1b45f579fc9f