信号量
dispatch_semaphore_create(long value);
- value: 信号量的起始值。 传递小于零的值将导致返回NULL。
- des: 当两个线程需要协调特定事件的完成时,为值传递零是有用的。 传递大于零的值对于管理有限的资源池非常有用,其中池大小等于该值。
- returned: 新创建的信号量,或失败时为NULL。
dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);
- desema: 信号量。 在此参数中传递NULL的结果是未定义的。
- timeout: 何时超时(请参阅dispatch_time)。 为方便起见,有DISPATCH_TIME_NOW和DISPATCH_TIME_FOREVER常量。
- des: 减少计数信号量。 如果结果值小于零,则此函数在返回之前等待信号发生。
- returned: 成功时返回零,如果超时,则返回非零。
dispatch_semaphore_signal(dispatch_semaphore_t dsema);
- desma: 信号量。 在此参数中传递NULL的结果是未定义的。
- des: 增加计数信号量。 如果前一个值小于零,则此函数在返回之前唤醒等待的线程。
- returned:如果线程被唤醒,则此函数返回非零值。 否则,返回零。
用法
控制线程数量
- 可以限制线程的并发数量
self.signal = dispatch_semaphore_create(10);
for (int i = 0; i < 1000; i++) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(self.signal, DISPATCH_TIME_FOREVER); //信号量-1
//...耗时操作
dispatch_semaphore_signal(self.signal);// 信号量+1
});
}
等待异步回调(强行同步代码块)
- 强行同步某些操作,例如在子线程内等待异步block调用完成,同步获取Block内的回调结果。
dispatch_async(self.queue, ^{
self.signal = dispatch_semaphore_create(1); //只允许一个信号量
int a = 0;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //开启一个耗时的异步Block
//异步的耗时操作,比如:睡眠3秒
[NSThread sleepForTimeInterval:3];
a = 1;
dispatch_semaphore_signal(self.signal);//释放信号量
});
dispatch_semaphore_wait(self.signal, DISPATCH_TIME_FOREVER); //锁住信号量
//等待异步回调完成后的操作。
NSLog(@"current a :%ld",(long)a);
});
其他语言相似的地方.
- golang的 waitgroup使用类似。
- java的notify,wait机制类似。
注意事项:不要轻易在主线程调用wait方法。在信号量小于0的情况下绝对会锁住当前主线程。
有疑问加站长微信联系(非本文作者)