一、多线程的基本概念
- 进程:可以理解成一个运行中的应用程序,是系统进行资源分配和调用的基本单位,是操作系统结构的基础,主要管理资源。
- 【线程】:进程的基本执行单元,一个进程拥有至少一个线程。
- 【主线程】:处理UI,所有更新UI的操作都必须在主线程上执行。
- 【多线程】:在同一时刻,一个CPU只能处理1条线程,但CPU可以在多条线程之间快速的切换,只要切换的速度足够快,就造成了多线程一同执行的假象。
线程就像火车的一节车厢,进程则是火车。车厢(线程)离开火车(进程)是无法跑动的,而火车(进程)至少有一节车厢(主线程)。多线程可以看作多个车厢,他的出现是为了提高效率,另外我们可以利用多线程,将耗时的操作放到后台执行,以防止耗时操作阻塞主线程,导致UI卡顿等现象。
线程的状态与生命周期
下图是线程状态示意图,从图中可以看出线程的生命周期:新建->就绪->运行->阻塞->死亡
下面分别阐述线程的生命周期中的每一步:
- 【新建】:实例化线程对象。
- 【就绪】:向线程对象发送start消息,线程对象被加入可调度线程池等待CPU调度。
- 【运行】:CPU负责调度可调度线程池中线程的执行。线程执行完成之前,状态可能会在就绪和运行之间来回切换。就绪和运行之间的状态变化由CPU负责,程序员不能干预。
- 【阻塞】:当满足某个预定条件时,可以使用休眠或锁,阻塞线程执行。
sleepForTimeInterval
(休眠指定时长),sleepUntilDate
(休眠到指定日期)@synchronized(self)
,:(互斥锁)。 - 【死亡】:正常死亡,线程执行完毕。非正常死亡,当满足某个条件后,在线程内部终止执行/在主线程终止线程对象。
补充:
[NSThread exit]
:一旦强行终止程序,后续的所有代码都不会被执行。[thread cancel]
:取消线程,并不会直接取消线程,只是给线程对象添加 isCancellled
标记。
多线程的四种解决方案
多线程的四种解决方案:pthread、NSThread、GCD、NSOperation
线程安全问题
当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题。
解决多线程安全问题
- 方法一:互斥锁
@synchronized(锁对象) {
// 需要锁定的代码
}
判断的时候锁对象要存在,如果代码中只有一个地方需要加锁,大多数都使用self作为锁对象,这样可以避免单独再创建一个锁对象。
加了互斥锁的代码,当新线程访问时,如果发现其他线程正在执行锁定的代码,新线程就会进入休眠。
- 方法二:自旋锁
加了自旋锁,当新线程访问代码时,如果发现其他线程正在锁定代码,新线程会采用死循环的方式,一直等待锁定的代码执行完成。相当于不停尝试执行代码,比较消耗性能。
修饰符atomic本身就有一把自旋锁。
atomic与noatomic:
atomic:原子属性(线程安全),保证同一时间只有一个线程能够写入(但是同一个时间多个线程都可以取值)
noatomic:非原子属性,同一时间可以被多个线程读写
atomic:线程安全,但是需要消耗的资源大
noatomic:非线程安全,不过效率很高
- 方法三:NSLock
创建一个NSLock对象,将需要锁定的代码放在lock
和Unlock
之间
// 初始化数据锁
NSLock *lock =[NSLock alloc]init];
// 数据加锁
[lock lock];
// do something 需要锁定的代码
// 数据解锁
[lock Unlock];