- GCD
- NSOperation
- NSThread
- 多线程与锁
GCD
- 同步/异步 和 串行/并发
- dispatch_barrier_async(多读单写)
- dispatch_group
同步/异步 和 串行/并发
- dispatch_sync(serial_queue,^{//任务});
- dispatch_async(serial_queue,^{//任务});
- dispatch_sync(concurrent_queue,^{//任务});
- dispatch_async(concurrent_queue,^{//任务});
同步串行
- (void)viewDidLoad {
dispatch_sync(dispatch_get_main_queue(),^{
//任务
[self doSomething];
});
}
产生死锁! 队列引起的循环等待
- (void)viewDidLoad {
dispatch_sync(serialQueue,^{
//任务
[self doSomething];
});
}
正常运行
同步并发
- (void)viewDidLoad {
NSLog(@"1");
dispatch_sync(global_queue,^{
NSLog(@"2");
dispatch_sync(global_queue,^{
NSLog(@"3");
});
NSLog(@"4");
});
NSLog(@"5");
}
输出结果:12345;
异步串行
- (void)viewDidLoad {
dispatch_sync(global_queue,^{
[self doSomething];
});
}
异步并发
- (void)viewDidLoad {
dispatch_sync(global_queue,^{
NSLog(@"1");
[self performSelector:@selector(printLog) withObject:nil afterDelay:0];
NSLog(@"3");
});
}
- (void)printLog{NSLog(@"2");};
输出结果:13;不会输出结果2;
dispatch_barrier_async() 怎样利用GCD实现多读单写?
- 读者、读者并发
- 读者、写者互斥
- 写者、写者互斥
多读单写实现流程
dispatch_barrier_async(concurrent_queue,^{//写操作});
dispatch_group_async() 使用GCD实现这个需求:A、B、C三个任务并发,完成后执行任务D?
多图上传,可变数据接受,然后,替换数组中的内容。
- (void)handle
{
dispatch_group_t group = dispatch_group_create();
for (NSURL *url in arrayURLs){
dispatch_group_async(group,concurrent_queue,^{
NSLog(@"url is %@",url);
}):
}
dispatch_group_notify(group,dispatch_get_main_queue(),^{
NSLog(@"所有图片下载完成");
});
}
NSOperation
需要和NSOperationQueue配合使用来实现多线程方案
- 添加任务依赖
- 任务执行状态控制
- 最大并发量
任务执行状态控制
- isReady
- isExecuting
- isFinished
- isCancelled
状态控制 如果只重写main方法,底层控制变更任务执行完成状态,以及任务退出。 如果重写了start方法,自行控制任务状态
源码(gnustep-base-1.24.9) 状态控制 系统是怎样移除一个isFinished=YES的NSOperation的? 答案:通过KVO。
NSThread
启动流程
创建runloop实现常驻线程。
start方法 源码(gnustep-base-1.24.9)
多线程与锁
iOS当中都有哪些锁?
- @synchronized
- atomic
- OSSpinLock
- NSRecursiveLock
- NSLock
- dispatch_semaphore_t
synchronized 一般在创建单例对象的时候使用,保证多线程下创建对象是唯一的
atomin 修饰属性关键字 对被修饰的对象进行原子操作(不负责使用) @property(atomic) NSMutableArray *array; self.array = [NSMutableArray array];(线程安全) [self.array addObject:obj];(线程不安全)
OSSpinLock 循环等待询问,不释放当前资源 用于轻量级数据访问,简单的int值+1/-1操作 (runtime的源码回答自旋锁)
NSLock
- (void)methodA{
[lock lock];
[self methodB];
[lock unlock];
}
- (void)methodB{
[lock lock];
//操作逻辑
[lock unlock];
}
以上会死锁,可以通过NSRecursiveLock解决
- (void)methodA{
[recursiveLock lock];
[self methodB];
[recursiveLock unlock];
}
- (void)methodB{
[recursiveLock lock];
//操作逻辑
[recursiveLock unlock];
}
递归锁可以重入,防止死锁。
dispatch_semaphore_t(信号量)
- dispatch_semaphore_create(1)
- dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
- dispatch_semaphore_signal(semaphore);
源码解析 dispatch_semaphore_create()
struct semaphore {
int value;
List`<thread>`;
}
dispatch_semaphore_wait()
{
S.value = S.value - 1;
if S.value <0 then Block(S.list); =>阻塞是一个主动行为。
}
dispatch_semaphore_signal()
S.value = S.value + 1;
if S.value <= 0 then wakeup(S.List); =>唤醒是一个被动行为
多线程总结
- 怎样用GCD实现多读单写?
- iOS系统为我们提供了几种多线程的技术各自的特点是怎样的?
- NSOperation对象在Finished之后是怎样从queue当中移除掉的?
- 你都用过哪些锁?结合实际谈谈你是怎样使用的?