当并行执行的处理更新数据时,会产生数据不一致,甚至出现异常结束的情况,使用Serial Dispatch Queue和dispatch_barrier_async函数可避免,但使用Dispatch Semaphore可以进行更细颗粒的排他控制。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSMutableArray *array = @[].mutableCopy;
for (int i = 0; i < 1000; i++) {
dispatch_async(queue, ^{
[array addObject:[NSNumber numberWithInt:i]];
});
}
说明:可能出现同时访问数组,造成异常结束的问题。
Dispatch Semaphore是持有计数的信号,该计数是多线程编程中的计数类型信号。
Dispatch Semaphore中,计数为0时等待,计数为1或者大于1时,减去1而不等待。
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
说明:
dispatch_semaphore_create函数生成Dispatch Semaphore。
参数表示计数的初始值。
含有create可以看出,该函数与Dispatch Queue和Dispatch Group一样,必须通过dispatch_release函数释放,也可以通过dispatch_retain函数持有。
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
说明:
该函数等待第一个参数semaphore的计数值达到大于等于1。
当计数值大于等于1,或者在待机(等待的时间)中计数值大于等于1,对该计数进行减1并从该函数返回。
第二个参数是dispatch_time_t类型值,与dispatch_group_wait函数相同。
DISPATCH_TIME_FOREVER:永久等待。
dispatch_semaphore_signal(semaphore);
说明:
处理结束时通过该函数将semaphore的计数值加1
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 1ull * NSEC_PER_SEC);
long result = dispatch_semaphore_wait(semaphore, time);
if (result == 0) {
// 由于semaphore的计数值大于等于1或在等待时间内计数值大于等于1, 所以semaphore的计数值减1 执行需要进行排他控制的处理
} else {
// semaphore的计数值直到1秒的等待时间结束都为0。
}
说明:
dispatch_semaphore_wait函数的返回值与dispatch_group_wait函数相同,semaphore大于等于1,result为0,semaphore为0,result不为0。
对数组的安全处理
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
NSMutableArray *array = @[].mutableCopy;
for (int i = 0; i < 1000; i++) {
dispatch_async(queue, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
[array addObject:[NSNumber numberWithInt:i]];
// 处理结束时通过该函数将semaphore的计数值加1
dispatch_semaphore_signal(semaphore);
});
}
// 使用结束,释放semaphore
dispatch_release(semaphore);