原文地址:http://blog.csdn.net/fhbystudy/article/details/25918451
我们在处理一系列线程的时候,当数量达到一定量,在以前我们可能会选择使用NSOperationQueue来处理并发控制,但如何在GCD中快速的控制并发呢?答案就是dispatch_semaphore,对经常做unix开发的人来讲,我所介绍的内容可能就显得非常入门级了,信号量在他们的多线程开发中再平常不过了。
信号量是一个整形值并且具有一个初始计数值,并且支持两个操作:信号通知和等待。当一个信号量被信号通知,其计数会被增加。当一个线程在一个信号量上等待时,线程会被阻塞(如果有必要的话),直至计数器大于零,然后线程会减少这个计数。
在GCD中有三个函数是semaphore的操作,分别是:
dispatch_semaphore_create 创建一个semaphore
dispatch_semaphore_signal 发送一个信号
dispatch_semaphore_wait 等待信号
简单的介绍一下这三个函数,第一个函数有一个整形的参数,我们可以理解为信号的总量,dispatch_semaphore_signal是发送一个信号,自然会让信号总量加1,dispatch_semaphore_wait等待信号,当信号总量少于0的时候就会一直等待,否则就可以正常的执行,并让信号总量-1,根据这样的原理,我们便可以快速的创建一个并发控制来同步任务和有限资源访问控制。
- (NSArray*)tasksForKeyPath:(NSString*)keyPath {
__blockNSArray*tasks =nil;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self.session getTasksWithCompletionHandler:^(NSArray*dataTasks,NSArray*uploadTasks,NSArray*downloadTasks) {if([keyPath isEqualToString:NSStringFromSelector(@selector(dataTasks))]) {
tasks = dataTasks;
}elseif([keyPath isEqualToString:NSStringFromSelector(@selector(uploadTasks))]) {
tasks = uploadTasks;
}elseif([keyPath isEqualToString:NSStringFromSelector(@selector(downloadTasks))]) {
tasks = downloadTasks;
}elseif([keyPath isEqualToString:NSStringFromSelector(@selector(tasks))]) {
tasks = [@[dataTasks, uploadTasks, downloadTasks] valueForKeyPath:@"@unionOfArrays.self"];
}
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);returntasks;}
getTasksWithCompletionHandler 这个方法是异步方法,上边的方法中我们需要等待这个异步方法有结果后才能进行后边的代码。 我们就可以使用dispatch_semaphore_t 这个信号来实现异步等待。
具体过程如下:
新建一个信号
在异步方法中发送信号,也就说一旦我们得到了异步的结果,我们就发一个信号
等待信号,只有接收到指定的信号代码才会往下走
这个信号的使用场景有很多,可以当安全锁来使用,也可以像上边一样异步等待。 假如我们有这样一个场景:我们有3个或者多个异步的网络请求,必须等待所有的请求回来后,在使用这些请求的结果来做一些事情。那么该怎么办呢? 解决方案就是:使用dispatch_group_t 和 dispatch_semaphore_t来实现。 在这里代码就不贴出来了,有兴趣的朋友而已自己google或者留言。