前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS多线程:GCD使用介绍

iOS多线程:GCD使用介绍

作者头像
用户5521279
发布2020-09-23 11:07:24
1.1K0
发布2020-09-23 11:07:24
举报
文章被收录于专栏:搜狗测试搜狗测试

背景

最近作者在进行多线程问题排查和整理时,发现了好多问题都是由于GCD的使用不规范造成的,因此在这里主要分享GCD的使用方法,希望大家能够在测试时更早发现问题。

GCD简介

GCD 为苹果推出的多核编程解决方案,它不仅能够自动利用多个核心处理数据,还能够自动管理生命周期,不需要程序猿手动管理。在日常的编程中十分常用。其优点如下:

  • GCD 可用于多核的并行运算;
  • GCD 会自动利用更多的 CPU 内核(比如双核、四核);
  • GCD 会自动管理线程的生命周期(创建线程、调度任务、销毁线程);
  • 程序员只需要告诉 GCD 想要执行什么任务,不需要编写任何线程管理代码。

GCD 任务和队列

学习 GCD 之前,先来了解 GCD 中两个核心概念:『任务』 和 『队列』。

任务:就是执行操作的意思,换句话说就是你在线程中执行的那段代码。在 GCD 中是放在 block 中的。执行任务有两种方式:『同步执行』 和 『异步执行』。两者的主要区别是:是否等待队列的任务执行结束,以及是否具备开启新线程的能力。

  • 同步执行(sync):
    • 同步添加任务到指定的队列中,在添加的任务执行结束之前,会一直等待,直到队列里面的任务完成之后再继续执行。
    • 只能在当前线程中执行任务,不具备开启新线程的能力。
  • 异步执行(async):
    • 异步添加任务到指定的队列中,它不会做任何等待,可以继续执行任务。
    • 可以在新的线程中执行任务,具备开启新线程的能力。

队列(Dispatch Queue):这里的队列指执行任务的等待队列,即用来存放任务的队列。队列是一种特殊的线性表,采用 FIFO(先进先出)的原则,即新任务总是被插入到队列的末尾,而读取任务的时候总是从队列的头部开始读取。每读取一个任务,则从队列中释放一个任务。队列的结构可参考下图:

在 GCD 中有两种队列:『串行队列』『并发队列』。两者都符合 FIFO(先进先出)的原则。两者的主要区别是:执行顺序不同,以及开启线程数不同。

  • 串行队列(Serial Dispatch Queue)
    • 每次只有一个任务被执行。让任务一个接着一个地执行。(只开启一个线程,一个任务执行完毕后,再执行下一个任务)
  • 并发队列(Concurrent Dispatch Queue)
    • 可以让多个任务并发(同时)执行。(可以开启多个线程,并且同时执行任务)

两者具体区别如下两图所示:

GCD 的使用步骤

GCD 的使用步骤其实很简单,只有两步:

  1. 创建一个队列(串行队列或并发队列);
  2. 将任务追加到任务的等待队列中,然后系统就会根据任务类型执行任务(同步执行或异步执行)。

下边来看看队列的创建方法 / 获取方法,以及任务的创建方法。

1. 创建队列

可以使用 dispatch_queue_create 方法来创建队列。该方法需要传入两个参数:

  • 第一个参数表示队列的唯一标识符,用于 DEBUG,可为空。队列的名称推荐使用应用程序 ID 这种逆序全程域名。
  • 第二个参数用来识别是串行队列还是并发队列。DISPATCH_QUEUE_SERIAL 表示串行队列,DISPATCH_QUEUE_CONCURRENT 表示并发队列。
代码语言:javascript
复制
// 串行队列的创建方法

2. 任务的创建方法

GCD 提供了同步执行任务的创建方法 dispatch_sync 和异步执行任务创建方法 dispatch_async

代码语言:javascript
复制
// 同步执行任务创建方法
dispatch_sync(queue, ^{
    // 这里放同步执行任务代码
});
// 异步执行任务创建方法
dispatch_async(queue, ^{
    // 这里放异步执行任务代码
});

虽然使用 GCD 只需两步,但是既然我们有两种队列(串行队列 / 并发队列),两种任务执行方式(同步执行 / 异步执行),如果当前代码默认放在主队列中,我们也有两种特殊的组合方式。于是我们就有了六种不同的组合方式。这四种不同的组合方式是:

同步执行 + 并发队列 异步执行 + 并发队列 同步执行 + 串行队列 异步执行 + 串行队列 同步执行 + 主队列 异步执行 + 主队列

我们先来考虑最基本的使用,也就是当前线程为 『主线程』 的环境下,『不同队列』+『不同任务』 简单组合使用的不同区别。暂时不考虑 『队列中嵌套队列』 的这种复杂情况。

『主线程』中,『不同队列』+『不同任务』简单组合的区别:

任务

并发队列

串行队列

主队列

同步(sync)

没有开启新线程,串行执行任务

没有开启新线程,串行执行任务

死锁卡住不执行

异步(async)

有开启新线程,串行执行任务

有开启新线程(1条),串行执行任务

没有开启新线程,串行执行任务

总结

GCD的使用看起来非常简单,但是在实际使用当中必须要严格遵循队列和任务的关系,以及内部数据的线程安全,防止出现概率崩溃及锁死的情况。GCD虽然非常好用,但也意味着其产生问题时会造成更大的影响,希望大家在测试过程中重点关注。






本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-09-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 搜狗测试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档