iOS 多线程

经常听到这样的问题 "你在处理多线程的时候 遇到过什么问题 或者说 你使用过多线程吗 如何操作的"

具体 我也没听过 别人是怎么回答的,我也没太想好怎样回答才算全面,今天利用工作空余时间好好系统学一下,从以下几个角度学习

1 理论

2 举例子运用

3 实际开发注意要点

一 理论

  1 线程和进程

      a 一般运行一个程序就是一个进程. 一个程序至少有一个进程,一个进程至少有一个线程

      b 线程,是进程的一部分,一个没有线程的进程可以被看作是单线程的 (相对进程而言,线程是一个更加接近于执行体的概念)

      c 进程可以创建线程 也可以创建进程 

      d 线程由进程管理,  线程之间  线程和父进程之间(创建线程的进程)共享内存变量 (需要策略实现)

      e 进程之间一般不可以直接共享内存变量,需要一些进程间的控制共享内存变量

  2 iOS 多线程编程技术(这里主讲GCD)

      NSThread  NSOperation  GCD

     (1) NSThread 

       优点: 使用起来比 其他两个更轻量级

       缺点:需要自己管理线程的生命周期,线程同步. 线程同步的加锁会又一定的系统开销

     (2)NSOperation 

       优点:无需关心线程管理,数据同步.关键是操作执行操作.

              相关类:抽象类 NSInvocationOperation 和 NSBlockOperation

              创建NSOperation子类对象,把对象添加到NSOperationqueue队列里执行

     (3)GCD (grand central dispatch)

        iOS4后开始使用,是代替以上两种多线程方法的强大技术,GCD中FIFO队列称为 dispatch queue

       dispatch queue :

       a  串行队列: serial 队列  队里任务 是一个一个地执行

       dispatch_queue_t  queue = dispatch_queue_create("com.xxx.serialQueue",DISPATCH_QUEUE_SERIAL);// 自己创建一个串行队列

       b  并行队列:concurrent 队列 通常任务会并发的执行     

       dispatch_queue_t  queue  =  dispatch_queue_create("com.xxx.concurrentQueue",DISPATCH_QUEUE_CONCURRENT);// 自己创建一个并行队列

      c 全局队列 : 系统级别的,直接拿来用,是一种并发队列

       dispatch_queue_t  queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);

      d 主队列 :一个应用程序对应唯一一个主队列,也是系统级别,直接拿来用,多线程开发使用主队列更新UI. 是一种串行队列

       dispatch_queue_t  queue = dispatch_get_main_queue();

 二 举例运用

  dispatch queue

#define global_queue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define main_queue dispatch_get_main_queue()

 (1)dispatch_async

     耗时懂得操作,数据处理,IO读取数据库什么的 在另一个线程中处理,然后通知主线程更新UI

     常用方法:

dispatch_async(global_queue, ^{
    //耗时间性能的处理放在这
    dispatch_sync(main_queue, ^{
        //主线程更新UI
    });
});

 (2)dispatch_group_async

   可以实现监听一组任务是否完成, 完成后得到通知再执行其他操作

   常用方法举例:下载 5张图片(或者说有五个独立数据请求),下载完了更新UI (都请求完成后执行其他操作)

- (void)fun
{
    // 创建一个组
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_async(group, global_queue, ^{
        //开启一个任务1
    });
    
    dispatch_group_async(group, global_queue, ^{
        // 开启一个任务2
    });
   //开启一个任务3
   //开启一个任务4
   //开启一个任务5
dispatch_group_notify(group, main_queue, ^{
// 等group中的所有任务都执行完毕, 再回到主线程执行其他操作
    });
}

 (3)dispathch_barrier_async(栅栏函数)

void dispatch_barrier_async ( dispatch_queue_t queue, dispatch_block_t block );

参数 queue: 将barrier添加到那个队列
block: barrier block 代码块

    "在它前面的的任务执行后它才执行,在它后面的任务需要等它执行完成后才能执行".

    使用情况是和并行队列一起使用,"同dispatch_queue_create函数生成的concurrent Dispatch Queue队列一起使用", 这个queue 一定是 自己创建的 并发队列,如果是 使用全局并发队列或者是一个串行队列,那么这个函数等同于dispatch_async函数.

 使用举例:

 

- (void)barrier
{
    dispatch_queue_t queue = dispatch_queue_create("myConcurrentQueue", DISPATCH_QUEUE_CONCURRENT);//这个queue 一定是 自己创建的 并发队列,如果是 使用全局并发队列或者是一个串行队列,那么这个函数等同于dispatch_async函数.
    
    dispatch_async(queue, ^{
        NSLog(@"任务1");
    });
    dispatch_async(queue, ^{
        NSLog(@"任务2");
    });
    
    dispatch_barrier_async(queue, ^{
        NSLog(@"barrier");
    });
    
    dispatch_async(queue, ^{
        NSLog(@"任务3");
    });
    dispatch_async(queue, ^{
        NSLog(@"任务4");
    });
}

打印结果

任务1

任务2 (1 和 2 并发 顺序不定)

barrier

任务3

任务4 (3 和 4 并发 顺序不定)

  (4)dispatch_apply

   执行N次的某一个代码片段 


dispatch_apply(5, global_queue, ^(size_t index){
     //此处任务执行5次
});

 

三 实际开发注意要点

     重点是关注多线程死锁问题,和正确选择多线程策略

     关于死锁,主要参考大学操作系统课程标配讲解:

     死锁原因

             (1)资源竞争 资源分配不当

             (2)系统资源不足

             (3)进程运行推进顺序不合适

     死锁条件:

           (1)互斥:进程在某一时间内独占资源

           (2)请求与保持:进程已经拥有当前资源,但是又申请新资源

           (3)不可剥夺: 进程的资源没使用完 就不可以强行从资源占有者处争夺资源

           (4)循环等待 : 出现闭环

     死锁预防:(破坏上述四个必要条件的一个或者几个)

          (1)破坏上述四个必要条件的一个或者几个 来防止死锁产生

          (2)鸵鸟算法,发生错误概率极小 可忽略

          (3)仔细检查对资源的动态分配情况,来预防死锁

          (4)检测死锁并且恢复

          (5)避免死锁的一个通用的经验法则是:当几个线程都要访问共享资源A、B、C时,保证使每个线程都按照同样的顺序去访问它们,比如都先访问A,在访问B和C。这样不会产生闭环.

   参考:

    https://developer.apple.com/reference/dispatch#//apple_ref/c/func/dispatch_barrier_async

 

posted on 2016-11-18 11:34  ACM_Someone like you  阅读(364)  评论(0编辑  收藏  举报

导航