GCD 信号量
这种情况下,将所有的数据追加到NSMutableArray中。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); NSMutableArray *array = [[NSMutableArray alloc]init]; for (int i = 0; i < 100000; i++) { dispatch_async(queue, ^{ [NSThread sleepForTimeInterval:3]; NSLog(@"task %@ %d",[NSThread currentThread],i); [array addObject:[NSNumber numberWithInt:i]]; }); }
因为该代码使用Global 更新NSMutableArray 类对象,所以执行后由内存错误导至应用异常结束的概率很高。应使用Dispatch Semaphore。
Dispatch Semaphore 信号量是一个整形值并且具有一个初始计数值,并且支持两个操作:信号通知和等待。当一个信号量被信号通知,其计数会被增加。当一个线程在一个信号量上等待时,线程会被阻塞(如果有必要的话),直至计数器大于零,然后线程会减少这个计数。
在GCD中有三个函数是semaphore的操作,分别是:
dispatch_semaphore_create 创建一个semaphore
dispatch_semaphore_signal 发送一个信号
dispatch_semaphore_wait 等待信号
简单的介绍一下这三个函数,第一个函数有一个整形的参数,我们可以理解为信号的总量,dispatch_semaphore_signal是发送一个信号,自然会让信号总量加1,dispatch_semaphore_wait等待信号,当信号总量少于0的时候就会一直等待,否则就可以正常的执行,并让信号总量-1,根据这样的原理,我们便可以快速的创建一个并发控制来同步任务和有限资源访问控制。
看代码
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); /** 生成Dispatch semaphore Dispatch semaphore得计数初始值是 “1” 保证可访问NSMutableArray 类对象的线程同时只能有6个 */ dispatch_semaphore_t semaphore = dispatch_semaphore_create(6); NSMutableArray *array = [[NSMutableArray alloc]init]; for (int i = 0; i < 100000; i++) { dispatch_async(queue, ^{ /** 等待直到Dispatch semaphore 计数值达到大于等于1 */ dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); [NSThread sleepForTimeInterval:3]; NSLog(@"task %@ %d",[NSThread currentThread],i); [array addObject:[NSNumber numberWithInt:i]]; /** 线程结束的时候会发送一个信号 */ dispatch_semaphore_signal(semaphore); }); }
创建了一个初使值为6的semaphore,每一次for循环都会创建一个新的线程,线程结束的时候会发送一个信号,线程创建之前会信号等待,所以当同时创建了6个线程之后,for循环就会阻塞,等待有线程结束之后会增加一个信号才继续执行,如此就形成了对并发的控制,如上就是一个并发数为6的一个线程队列。