一、信号量
信号量是控制资源访问数量的标识
当信号量大于 0 时,可以访问资源;当信号量等于 0 时无法访问资源
// 创建一个 semaphore
dispatch_semaphore_create
// 发送一个信号
dispatch_semaphore_signal
// 等待可用信号访问资源
dispatch_semaphore_wait
1、控制资源访问并发数
dispatch_queue_t queue = dispatch_queue_create("并行队列", DISPATCH_QUEUE_CONCURRENT);
dispatch_semaphore_t dsema = dispatch_semaphore_create(4);
for (NSInteger i = 0; i < 10; i++) {
dispatch_async(queue, ^{
dispatch_semaphore_wait(dsema, DISPATCH_TIME_FOREVER);
sleep(3);
NSLog(@"%ld", i);
dispatch_semaphore_signal(dsema);
});
}
2、将异步执行任务切换为同步执行任务
dispatch_semaphore_t dsema = dispatch_semaphore_create(0);
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
NSLog(@"耗时任务开始");
sleep(3);
NSLog(@"耗时任务结束");
dispatch_semaphore_signal(dsema);
});
dispatch_semaphore_wait(dsema, DISPATCH_TIME_FOREVER);
NSLog(@"刷新 UI");
二、栅栏
栅栏任务会对任务队列进行分割实现如下效果:
栅栏任务之前的任务执行完成之后开始执行栅栏任务。
栅栏任务之后的任务在栅栏任务执行完成之后开始执行
1、栅栏只对自定义队列即 dispatch_queue_create 创建的队列有效。
2、两个重要函数
异步地添加任务
dispatch_barrier_async(queue, ^{
});
同步地添加执行
dispatch_barrier_sync(queue, ^{
});
3、栅栏作用的效果测试
for (NSInteger i = 1; i <= 20; i++) {
if (i == 6) {
dispatch_barrier_async(queue, ^{
sleep((arc4random() % 100 + 50) / 100.0);
NSLog(@"%ld", i);
});
} else if (i == 11) {
dispatch_barrier_async(queue, ^{
sleep((arc4random() % 100 + 50) / 100.0);
NSLog(@"%ld", i);
});
} else {
dispatch_async(queue, ^{
sleep((arc4random() % 100 + 50) / 100.0);
NSLog(@"%ld", i);
});
}
}
4、多线程、安全地对数据进行读写操作
在并行队列中,异步地添加读取任务,异步(同步也可以)地添加栅栏写入任务。
效果:每次写入任务之前的读取任务必须执行完成之后才会执行本次写入任务;
_queue = dispatch_queue_create("custom", DISPATCH_QUEUE_CONCURRENT);
- (NSString *)name {
__block NSString *name;
dispatch_async(_queue, ^{
name = self->_name;
});
return name;
}
- (void)setName:(NSString *)name {
dispatch_barrier_async(_queue, ^{
self->_name = name;
});
}