objc.io issue2 并发编程 笔记1

原文连接 http://www.objc.io/issue-2/concurrency-apis-and-pitfalls.htmlhtml

已经有中文版了: http://beyondvincent.com/blog/2013/07/16/104/ 算法

原本想本身一边翻译一遍看的,结果发现量有点大,还要调整配图,麻烦,就算了。就记下要点吧。编程

1. 并发包含单核的分时系统和真正的多核系统api

2. OS X/iOS 包含一组API: GCD, NSOperationQueue, pthread/NSThread (NSRunLoop只是很是相关)安全

3. 可使用Instruments的 CPU strategy view来观察CPU cores的利用状况网络

4. pthread兼容POSIX, NSThread是pthread的外包类, 写起来相对复杂,不推荐直接使用并发

5. 若是本身也使用pthread,所用的库的实现也用了pthread,那么和可能来个乘法效应,好比库探测出硬件有4核,因而生成4个线程;每一个线程里面插入了本身的干活代码,这里也分配了4个线程..等等。冗余的线程是有内存和内核开销的。函数

6. 基于队列的API, 建立一个线程池来控制工具

6.1 GCD  oop

    直接考虑干活的block代码,而非关注线程自己。具体参考图。

    主线程  ---  主队列(串行队列)

    GCD线程池   ---  高中低以及背景优先级队列(以默认的中优先级队列为例,能够设置串行队列,也能够设置并行队列,后者再塞入串行队列)

    GCD很底层也很方便,但仍然要当心并发编程的各类警告和陷阱(见后文)

6.2 OperationQueue

    基于GCD之上,足够的弹性而且这种封装也避免了直接使用GCD容易产生的一些问题

    NSOperationQueue分两种,主线程上跑的main queue和别的线程上跑的自定义queue,工做任务被封装成NSOperation,能够重写NSOperation的main/start/finished

    NSOperationQueue也能够直接加入block。

    他们很是适合于调试: 重载description函数能够输入内部的各类细节状态

    其余有用的参数: maxConcurrentOperationCount  设置为1就是串行的队列,减小了任务之间的冲突。

    还能够在NSOperation之间 addDependency,控制启动顺序(以及更重要的,是否是必须等运行完毕了再启动!)

    小结: 相比直接使用GCD,代价轻微,很是实用,最优先的工具。

7 Run Loops 主线程有个默认的NSRunloop, 在操做时自动切换模式(优先处理输入)。给其余线程的Runloop作设置时要加一个source,不然直接退出。具体例子见本系列其余文章

8 并发编程的挑战(通用知识,能够自行找相关书籍看,好比深刻理解计算机系统什么的)

    8.1 资源分享 资源能够是一个对象,通用内存,网络设备,文件等等。容易产生hazard, 好比A、B线程都给某个值为17的变量增长1,A增长以后还没有写回时,B读取后再增长,因而两次写入都是18,结果是18而不是期待的19,这就是race condition 竞态条件,因为现代cpu的乱序执行可能问题更加复杂。

    8.2 为了解决race condition,引入mutal exclusion,资源锁,锁定原子级(atomic)操做。锁自己还要支持乱序执行下的正确性,因而须要插入memory barrier保证cpu语意正确,因此自己开销就比较大。 锁的设计也有多种,有的是当没有锁上时,开销很小但一旦资源有锁,开销就很大;有些则是在基础状况下开销更高一些,可是在资源有锁的状况下的开销会相对好一些。若是几个线程在竞争使用某个资源,那么效率可能至关低。

    8.3 锁还带来了另外一个严重问题: Dead lock 死锁。举例: 线程A 拿到资源1,等着拿到资源2后继续干活;线程B拿到资源2,等着拿到资源1继续干活。因而你们一直在等待。因此尽量保持简单,避免死锁的出现。系列的其余文章会详述这些问题。

    8.4 饥饿/Starvation 通常状况下,对于一个资源能够有多个只读的锁和一个写的锁。有只读的锁的状况下能够继续加只读锁,结果致使写的锁一直在等待全部的只读锁退出后再去写。 readers-writers problem,解决办法是writers preference / read-copy-update 算法

    8.5 优先级反转 Priority Inversion  高中低三个线程。低优先级的线程锁住了高优先级的线程须要的资源,这时候高优先级的线程锁不上资源因而等着;低优先级的线程因为被中优先级的线程压制,无法得到运行时间释放资源。结论是别用不一样的优先级啦,一不当心就优先级反转了。NASA在火星探路者上的遭遇代表,即便是颇有经验的工程师也可能碰到这种问题。

9 总结 安全模式之一: 主线程丢出去数据,用操做队列在后台作实际的工做,作完后把结果回报给主线程的主队列main queue。 这样就避免了各类锁,减小错误的可能性。

 

2013.09.17

相关文章
相关标签/搜索