多线程编程(一)多线程基础

序言

当前使用的大多数操作系统都能同时运行多个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行的任务流,我们称之为线程。线程提供了多任务处理的能力。

用进程和线程的观点来研究软件是当今普遍采用的做法,进程和线程的概念的出现,对提高软件的并行性有着重要的意义。现在多芯处理器是常见的,即使在桌面和笔记本电脑的机器,在一个进程里面使用多线程,如果应有程序合适的话,能够让进程更好的利用硬件资源。

现在大部分的App都是多线程多任务处理,单线程的软件是不可想象的。因此掌握多线程多任务设计的方法对每个程序员都是必需要掌握的。本章我们将会学习使用多种方式编写多线程应用程序。

每个 iOS 应用程序都有个专门用来更新显示 UI 界面、处理用户的触摸事件的主线程,因此不能将其他太耗时的操作放在主线程中执行,不然会造成主线程堵塞(出现卡机现象),带来不好的用户体验。一般的解决方案就是:将那些耗时的操作放到另外一个线程中去执行,多线程编程就是防止主线程堵塞和增加运行效率的最佳方法。

  学习多线程是一个非常漫长的过程,首先我们先来了解以下两点:
   1. 什么是多线程;
   2. 多线程中的基本概念;
  了解以上两点,对我们掌握任意语言环境下的多线程技术都是有着很大的帮助的。

1. 什么是多线程

我们先来解决第一个问题:什么是多线程?

   Apple给出的多线程编程定义:
   Threads are a relatively lightweight way to implement multiple paths of execution inside of an application.
   翻译: 线程是一个相对轻量级的,在应用程序内部,实现任务执行的多条路径的方式。

看生活中的一个例子,车站售票时如果仅仅有一个窗口售票,我们可以把售票系统看作为单线程,如果旅客过多(任务过多)时,就会造成售票过慢的问题,这时只需增加售票窗口同时售票,来加快售票速度。这就是多线程。


2. 多线程中的基本概念

2.1 线程与进程

进程(Process):在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体,每个正在硬件上运行的程序都是一个进程,也可能是整个程序或是部分程序的动态执行,一般的应用程序是单个进程的,也有多个进程的(谷歌浏览器);iPhone4之前是不支持多任务的,即只有一个进程在执行。

进程是静态的容器,里面容纳了很多个线程,

线程(Thread):最开始,线程只是用于分配单个处理器的处理时间的一种工具。有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。线程一般是一系列的方法的线性执行路径,是一组指令(方法)的集合,或是程序的特殊段,可以在程序中独立执行。也可以将线程理解为代码运行的上下文,负责在程序中执行多任务,通常由操作系统负责多个线程的调度和执行

进程与线程的区别:子进程与父进程有不同的代码与数据空间,多个线程则共用一个数据空间。通常,在线程间进行转换要求操作系统所需要做的事比在进程间进行转换要少得多,所以多线程在资源的要求比多进程低得多。

2.2 多线程

概念:单个程序中同时运行多个线程完成不同的任务,称为多线程。

是指软件或硬件上实现多个线程并发执行的技术。需要强调的是,if_else区分执行不同的代码只是在一个线程中完成不同的任务,并不是多线程。

作用:节约CPU时间,避免程序卡死。

多线程是在同一时间完成多项任务是实现的。多线程并不能提高运行效率,而是可以同时执行多个任务,通过提高资源的使用效率来提高系统的效率。线程是在同一时间需要完成多项任务的时候实现的。

注意:多个线程并发导致的问题是,由于资源共享,多个线程可能会访问同一个资源,这要求多线程共享的资源需要在被使用时进入死锁状态,这点在我们后面学习多线程工具时会具体的讲到。

    举个例子来说,两个线程同时售票,不能同时把最后一张票卖给两个人。为解决这个问题,对那些可共享的资源来说(比如说售票系统),它们在使用期间必须进入锁定状态。所以一个线程可将资源锁定,在完成了它的任务后,再解开(释放)这个锁,使其他线程可以接着使用同样的资源。

优点:具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。比如说做饭,等多线程相当于煮饭的时候同时做菜洗碗,能在一根时间轴上进行多个作业从而在相同维度下尽量短的时间内完成作业。

2.3 并行,并发与串行:

并行:一组程序按独立异步的速度执行,即两行代码同时执行,注意这里不是同一时间发生,并行只是任务执行的时间上有重叠罢了,要区别于并发。

并发:在同一时间段内,两个或多个程序同时开始执行,这里说的事宏观意义上的同时,只有多核处理器才能真正做到微观上的真正的同时。

串行:与并行相对,几个任务之间依次执行。即任务执行的时间上没有重叠。

2.4 同步与异步
同步:是指两个任务之间的关系,一个任务需要等待另一个任务的反馈结果才能继续执行(打电话下达通知,只有别人接电话才能完成通知的下达)
异步:与同步的概念相对,一个任务不需要等待其他任务的反馈也可以继续执行。(发短信下达通知,)

   理解上面的几个概念对我们学习和使用多线程来说至关重要,而在理解上,同步异步与并行串行的概念很容易搞混,下面举一个例子来帮助我们来加深对上述几个概念的理解。
   在田径赛场上,以上概念均可以体现出来。把每个运动员看成一行代码,运动员奔跑代表开始执行任务,跑完全程代表任务结束。
  • 线程就像一条一条跑道,不同的运动员在不同的跑道上,可以达到互不干扰的目的,这也是多线程的作用。
  • 进程就像竞技场,每个竞技场都有自己的跑道,也就是说进程是线程的容器。在80年代以前,是没有线程概念的。而每次开启新的进程开销过大,就像一个竞技场只有一条跑道,新建竞技场需要花费的资源要远远大于多画一条跑道的成本。为了节约成本,就诞生了线程编程。
  • 并行表示两个跑道之间的关系,运动员在两条跑道上奔跑是可以互不干扰的,任务的开始结束不会受到另个一任务的干扰。
  • 串行就像接力赛,运动员之间需要交接接力棒。也就是说一个任务完成下一个任务才能开始。
  • 并发是指并行的两个任务同时发生,就像运动员起跑,描述的是一个时间关系。但是起跑肯定有快有慢,有可能做不到完全同时。并发宏观是同时,微观有可能不是同时。
  • 同步是描述两个事件交互时的概念,比如比赛开始前,裁判通知运动员入场,只有当运动员全部入场之后比赛才能正式开始,而在运动员入场过程中,裁判处于等待状态,也就是说,同步会导致程序阻塞。
  • 异步是和同步概念对应的,在裁判通知运动员入场后,不等待运动员入场直接开始比赛。

3. iOS提供的多线程技术

   iOS 支持多个层次的多线程编程,层次越高的抽象程度越高,使用也越方便,也是 Apple 最推荐使用的方法。下面是 iOS 所支持的多线程编程方法,抽象层次从低到高:
  • NSThread :是三种方法里面相对轻量级的,但需要管理线程的生命周期、同步、加锁问题,这会导致一定的性能开销
  • NSOperation:是基于 OC 实现的,NSOperation 以面向对象的方式封装了需要执行的操作,不必关心线程管理、同步等问题。
  • Grand Central Dispatch(简称 GCD ,iOS4 才开始支持):提供了一些新特性、运行库来支持多核并行编程,他的关注点更高:如何在多个 CPU 上提升效率

小结:

   在整个学习多线程的过程中,主要有两点能力是需要我们提高的,一是多线程工具的使用能力,二是多线程思维。要习惯使用多线程的方式去解决问题,但是培养多线程的编程思想需要我们用更长的时间去习惯和完善。在接下来的几节中,我们主要介绍的是多线程工具的使用。

猜你喜欢

转载自blog.csdn.net/qq_32510689/article/details/51723302