当我们在处理一系列线程的时候,当数量达到一定量,在以前我们可能会选择使用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,根据这样的原理,我们便可以快速的创建一个并发控制来同步任务和有限资源访问控制
int data = 3; __block int mainData = 0; __block dispatch_semaphore_t sem = dispatch_semaphore_create(0); dispatch_queue_t queue = dispatch_queue_create("StudyBlocks", NULL); dispatch_async(queue, ^(void) { int sum = 0; for(int i = 0; i < 5; i++) { sum += data; NSLog(@" >> Sum: %d", sum); } dispatch_semaphore_signal(sem); }); dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); for(int j=0;j<5;j++) { mainData++; NSLog(@">> Main Data: %d",mainData); } dispatch_release(sem); dispatch_release(queue); 输出: 2013-07-08 11:33:05.654 dispatch[1102:1e03] >> Sum: 3 2013-07-08 11:33:05.656 dispatch[1102:1e03] >> Sum: 6 2013-07-08 11:33:05.657 dispatch[1102:1e03] >> Sum: 9 2013-07-08 11:33:05.658 dispatch[1102:1e03] >> Sum: 12 2013-07-08 11:33:05.659 dispatch[1102:1e03] >> Sum: 15 2013-07-08 11:33:05.660 dispatch[1102:c07] >> Main Data: 1 2013-07-08 11:33:05.660 dispatch[1102:c07] >> Main Data: 2 2013-07-08 11:33:05.660 dispatch[1102:c07] >> Main Data: 3 2013-07-08 11:33:05.661 dispatch[1102:c07] >> Main Data: 4 2013-07-08 11:33:05.661 dispatch[1102:c07] >> Main Data: 5 通过信号量就可以保证,Main Data 永远在Sum之后执行
__block BOOL isok = NO; dispatch_semaphore_t sema = dispatch_semaphore_create(0); Engine *engine = [[Engine alloc] init]; [engine queryCompletion:^(BOOL isOpen) { isok = isOpen; dispatch_semaphore_signal(sema); } onError:^(int errorCode, NSString *errorMessage) { isok = NO; dispatch_semaphore_signal(sema); }]; dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); dispatch_release(sema);