博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS 多线程
阅读量:7175 次
发布时间:2019-06-29

本文共 3590 字,大约阅读时间需要 11 分钟。

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

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

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

 

转载于:https://www.cnblogs.com/someonelikeyou/p/5910168.html

你可能感兴趣的文章
数组中出现次数超过一半的数字
查看>>
学习Python第一天,命令很多跟Linux还有脚本语言相似。
查看>>
BEvent_客制化Event Agent通道(案例)(待整理)
查看>>
读书笔记 effective c++ Item 10 让赋值运算符返回指向*this的引用
查看>>
重中之重——》网站的外链建设如何进行?
查看>>
软件工程第三次作业——用户体验分析:以“南通大学教务学生管理系统”为例...
查看>>
TAE SDK 2.0.0工具 Update 7下载(12月13日更新)
查看>>
swift学习记录之代理
查看>>
hadoop分布式存储(1)-hadoop基础概念
查看>>
VMware虚拟机和主机(macOS)联网的解决方案
查看>>
nginx+awstats安装过程
查看>>
npm install --save 与 npm install --save-dev 的区别
查看>>
IE8 兼容CSS3 rgba属性
查看>>
Hadoop HA和Hbase HA
查看>>
获取div的高度
查看>>
制作自适应布局的模块及框架(转载)
查看>>
Python自动化运维之2、运算符与数据类型
查看>>
08.Python网络爬虫之图片懒加载技术、selenium和PhantomJS
查看>>
黑马程序员--预处理
查看>>
NSBundle
查看>>