信号量函数说明:
// 1、创建一个值为n信号量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(n);
// 2、如果该信号量的值大于0,则使其信号量的值-1;否则阻塞线程直到该信号量的值大于0或者达到等待时间。
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
// 3、释放信号量,使得该信号量的值加1
dispatch_semaphore_signal(信号量)
一般信号量的使用流程:
- 创建一个初始值为n信号量dispatch_semaphore_create;
- 在要执行任务的前面加入dispatch_semaphore_wait;
- 当其信号量的值大于0时则会执行这个任务,如小于等于0,则会一直阻塞当前线程;
- 执行完当前任务后调用dispatch_semaphore_signal;
使用场景
1、限制线程的最大并发数
dispatch_semaphore_t sema = dispatch_semaphore_create(m);
for (NSInteger i = 0; i<n; i++) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
// doing
dispatch_semaphore_signal(sema);
});
}
如上述代码可知,总共异步执行n个任务,但是由于我们设置了值为m的信号量,每一次执行任务的时候都会导致信号量的减1,而在任务结束后使信号量加1,当信号量减到0的时候,说明正在执行的任务有m个,这个时候其它任务就会阻塞,直到有任务被完成时,剩余的任务才会执行。
2、阻塞发请求的线程
有些时候,我们需要阻塞发送请求的线程,比如在多个请求回调后统一操作的需求,而这些请求之间并没有顺序关系,且这些接口都会另开线程进行网络请求的。一般地,这种多线程完成后进行统一操作的需求都会使用队列组(dispatch_group_t)来完成,但是由于是异步请求,没等其异步回调之后,请求的线程就结束了,为此,就需要使用信号量来阻塞住发请求的线程。实现代码如下:
dispatch_async(queue, 0), ^{
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[网络请求: ^{
// 请求回调
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
});
这样,请求的线程就可以等到回调结束后再结束了,再配合队列组就能完成上述的需求。这种技巧可用于以下场景:
- 多个请求结束后统一操作
- 多个请求顺序执行