多线程编程指南
Threading Programming Guide的中文翻译版本,由于个人精力有限,很多地方必然会出现错误,希望我们共同修改,另一个目的也是作为个人笔记之用。如要转载请注明出处
!
文章梳理
个人最后面进行一个梳理,肯定会有理解不到的地方,如果不想看可直接跳过。
一、线程创建
- 线程技术包括NSThread,posix等等。具体创建见“线程管理”一节。
- 如果不使用Runloop的话,线程在完成了入口点函数之后当前线程就会退出,为了保持线程常驻,我们需要Runloop。
二、Runloop
- 苹果不允许直接创建Runloop,每个线程在创建时系统会为他创建一个Runloop,用
[NSRunLoop currentRunLoop]
获取,或者在CoreFoundation中使用CFRunLoopGetCurrent()
; - 同样为了能够让Runloop能够一直循环下去(如果要Runloop退出可以设定超时时间),我们必须要为其添加输入源(事件源)抑或定时器源或者Observer,而这些源必须要添加到Mode中。
- 如果在Runloop中,我们不想去添加定时器源,或者输入源。最简单的办法就是在Runloop中添加一个Port:
NSPort *port = [NSMachPort port];
if (!port) {
return;
}
[port setDelegate:self];
[[NSRunLoop currentRunLoop] addPort:port forMode:NSDefaultRunLoopMode];
[NSThread detachNewThreadSelector:@selector(detachThread:) toTarget:self withObject:nil];
上诉知识具体见"Runloop"一节。
三、同步工具
在多线程程序中如果发生了对特定资源的竞争,这时就需要使用同步工具。由于使用同步工具会造成性能消耗,建议如下:
并发任务的最好的实现办法就是减少交互和相互依赖。如果每一个任务都是在它私有的数据集上做操作,这种情况就不需要使用锁来保护数据。就算是两个任务同时使用同一份数据集,我们可以让该数据集进行分区使用,或者为每一个任务复制一份数据。当然,复制数据也是有消耗的,所以就得衡量一下谁的消耗更高。
- 如果多个线程同时去获取特定资源,而且该资源被加锁,那么必须要先获取锁然后才能获取相应的资源。
- 同时在获取锁时,如果是互斥锁的话,必须要等到前一个线程释放该锁之后,另一个线程才能去获取该锁,获取了该锁然后获取资源。
上诉知识具体见"同步"一节。
四、总结
来总结一波:
因为在主线程执行耗时操作会影响用户体验 -----> 所以我们得需要使用多线程技术(子线程)-----> 由于子线程在执行一次之后就会退出,所以我们的使用Runloop(Runloop的保活又需要使用Mode) -----> 由于多线程在资源争夺方面的问题 -----> 我们得使用锁 -----> 由于使用多个锁的时候会造成死锁或者活动锁 -----> 所以我们在同一时刻最好的办法就是只用一个锁。
五、配套DEMO
[Github]Thread_Programming;