iOS 多线程开发之概念

386 阅读6分钟

iOS 多线程开发之系列文章

iOS 多线程开发之概念

iOS 多线程开发之 Thread

iOS 多线程开发之 GCD

iOS 多线程开发之 Operation

iOS 多线程开发之线程安全

多线程开发是日常开发任务中不可缺少的一部分,在 iOS 开发中常用到的多线程开发技术有 GCD、OperationThread,本文主要讲解多线系列文章中关于 概念及术语 相关知识。

术语

  • 进程(Process)

    指的是一个正在运行中的可执行文件。每一个进程都拥有独立的虚拟内存空间和系统资源,包括端口权限等,且至少包含一个主线程和任意数量的辅助线程。另外,当一个进程的主线程退出时,这个进程就结束了;

  • 线程(Thread)

    指的是一个独立的代码执行路径,也就是说线程是代码执行路径的最小分支。在 iOS 中,线程的底层实现是基于 POSIX Threads API 的,也就是我们常说的 pthreads;

  • 主线程(MainThread)

    处理UI,所有更新UI的操作都必须在主线程上执行。不要把耗时操作放在主线程,会卡界面。

  • 多线程(MultiThread)

    是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。在同一时刻,一个 CPU 只能处理一条线程,但 CPU 可以在多条线程之间快速的切换,只要切换的足够快,就造成了多线程一同执行的假象。

  • 任务(Task)

    指的是我们需要执行的工作,是一个抽象的概念,用通俗的话说,就是一段代码。

  • 同步(Sync)

    只能在当前线程按先后顺序依次执行,不开启新线程。

  • 异步(Async)

    可以在当前线程开启多个新线程执行,可不按顺序执行。异步是多线程的代名词

  • 队列(Queue):

    装载线程任务的队形结构。系统以 FIFO(先进先出)的方式调度队列中的任务执行。

image.png

  • 并发队列(Concurrent Queue):

    线程可以同时一起进行执行。实际上是CPU在多条线程之间快速的切换。(并发功能只有在异步(dispatch_async)函数下才有效)

image.png

  • 串行队列(Serial Queue):

    线程只能依次有序的执行

image.png

注意:

  • 一个进程可有多个线程。

  • 一个进程可有多个队列。

  • 队列可分并发队列和串行队列。

多线程优缺点

  • 优点:

    1. 能适当提高程序的执行效率。
    2. 能适当提高资源的利用率,比如 CPU,内存等。
    3. 线程上的任务执行结束后,线程会自动销毁。
  • 缺点:

    1. 开启线程需要占用一定的内存空间,默认情况下,每个线程都占 512 KB,如果开启大量的线程,会占用较大空间,降低程序性能。
    2. 线程越多,CPU 在调用上的开销就越大。
    3. 程序设计更加复杂,比如线程之间的通信,多线程数据共享等。

线程的状态与生命周期

  • 新建

    实例化线程对象。

  • 就绪

    向线程对象发送start消息,线程对象被加入可调度线程池等待CPU调度。

  • 运行

    CPU 负责调度可调度线程池中线程的执行。线程执行完成之前,状态可能会在就绪和运行之间来回切换。就绪和运行之间的状态变化由CPU负责,程序员不能干预。

  • 阻塞

    当满足某个预定条件时,可以使用休眠或锁,阻塞线程执行。sleepForTimeInterval(休眠指定时长),sleepUntilDate(休眠到指定日期),@synchronized(self):(互斥锁)。

  • 死亡

    正常死亡,线程执行完毕。非正常死亡,当满足某个条件后,在线程内部中止执行或在主线程中止线程对象。[NSThread exit]一旦强行终止线程,后续的所有代码都不会被执行。线程外死亡,[thread cancel] 并不会直接取消线程,只是给线程对象添加isCancelled标记。死亡后线程对象的 isFinished属性为YES;如果是发送calcel消息,线程对象的isCancelled 属性为YES;死亡后 stackSize == 0,内存空间被释放。

线程的状态转换

  • 如果CPU现在调度当前线程对象,则当前线程对象进入运行状态,如果 CPU 调度其他线程对象,则当前线程对象回到就绪状态。

  • 如果 CPU 在运行当前线程对象的时候调用了 Sleep 方法等待同步锁,则当前线程对象就进入了阻塞状态,等到 Sleep 到时得到同步锁,则回到就绪状态。

  • 如果 CPU 在运行当前线程对象的时候线程任务执行完毕\异常强制退出,则当前线程对象进入死亡状态。

只看文字可能不太好理解,具体当前线程对象的状态变化如下图所示。

image.png

多线程的四种解决方案

  • Pthread

    运用 C 语言,是一套通用的 API,可跨平台 Unix/Linux/Windows。线程的生命周期由程序员管理。

  • Thread

    面向对象,可直接操作线程对象。线程的生命周期由程序员管理。

  • GCD

    代替 Thread,可以充分利用设备的多核,自动管理线程生命周期。

  • Operation

    底层是 GCD,比 GCD 多了一些方法,更加面向对象,自动管理线程生命周期。

多线程对比

image.png

四种多线程技术的优缺点

Thread

每个 Thread 对象对应一个线程,真正最原始的线程。

  • 优点:Thread 轻量级最低,相对简单。

  • 缺点:手动管理所有的线程活动,如生命周期、线程同步、睡眠等。

Operation

自带线程管理的抽象类。

  • 优点:自带线程周期管理,操作上可更注重自己逻辑。

  • 缺点:面向对象的抽象类,只能实现它或者使用它定义好的子类 BlockOperation

GCD

Grand Central Dispatch (GCD)是 Apple 开发的一个多核编程的解决方法。

  • 优点:最高效,避开并发陷阱。

  • 缺点:基于 C 实现。

选择小结

  • 简单而安全的选择 Operation 实现多线程即可。

  • 处理大量并发数据,又追求性能效率的选择 GCD。

  • Thread 本人选择基本上是在做些小测试上使用,当然也可以基于此造个轮子。