iOS开发——多线程
Posted 执着的怪味豆
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS开发——多线程相关的知识,希望对你有一定的参考价值。
很多朋友都说ios开发中,最难理解和学习的就是多线程,很多的原理实现都是通过log看到,也比较抽象,本人也是在多线程方面投入过很多脑细胞。。无论这方面的知识掌握和应用起来是否轻松,牢固的基本功、正确的认识理解、再加上充分的实战经验,都能助你将其搞定。这里先介绍一些多线程的知识以及应用,作为讨论,大家共同学习。
一、多线程基本概念
1、线程与进程
(1)进程:操作系统的每一个应用程序就是一个进程
(2)线程:进程的基本执行单元,一个进程的所有任务都在线程中执行
2、主线程
(1)定义:一个程序运行后,默认会开启1个线程,称为“主线程”或“UI线程”。其他为“子线程”。
(2)作用及注意:线程一般用来 刷新UI界面 ,处理UI事件(比如:点击、滚动、拖拽等事件),避免将耗时的操作放到主线程,以免造成主线程卡顿。
3、多线程原理:
(1)是CPU快速的在多个线程之间的切换(自身的随机调度算法)。
(2)同步/异步:
- 同步:指的就是在当前线程(不一定是主线程)中,从上而下依次执行任务(代码块的阅读顺序),这个就叫做同步。
- 异步:指不在当前线程中执行了,开辟新的线程执行, 注意:即使在别的线程中执行,也是从上而下依次执行的。
4、iOS多线程实现方案
5、线程的占用空间:
(1)子线程:512KB。
(2)主线程:512KB。这里官方文档给出的是1M,实际测试为512,可以打印线程的stackSize属性验证。
6、线程的状态和生命周期:
(1)控制线程的状态(以NSThread管理线程为例)
a、启动线程:- (void)start;
线程进入就绪状态,当线程执行完毕后自动进入死亡状态。
b、暂停(阻塞)线程
+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
线程进入阻塞状态
c、停止线程
+ (void)exit;
线程进入死亡状态
(2)状态图
7、线程的属性(以NSThread管理线程为例,一下是NSTread类中的方法或属性)
(1)stackSize:占内存大小
(2)name:名字
(3)threadPriority:优先级(不推荐使用)
(4) qualityOfService:服务质量
二、多线程深入理解
1、线程间资源共享/抢夺
(1)定义:一块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源,当多个线程访问同一块资源时,各个线程提取和修改数据不同步,很容易引发数据错乱和数据安全问题。
(2)互斥锁(线程同步) :解决上面的问题
- 代码:@synchronized(锁对象) { 需要锁定的代码 }
- 每一个对象(NSObject)内部都有一个锁(变量),当有线程要进入synchronized到代码块中会先检查对象的锁是打开还是关闭状态,默认锁是打开状态(1),如果是线程执行到代码块内部 会先上锁(0)。如果锁被关闭,再有线程要执行代码块就先等待,直到锁打开才可以进入。
- 互斥锁的实现流程
线程执行到synchronized
i. 检查锁状态 如果是开锁状态转到ii ,如果上锁转到v
ii. 上锁(0)
iii. 执行代码块
iv. 执行完毕 开锁(1)
v. 线程等待(就绪状态)
- 注意:必须使用全局对象来提供“锁”,否则同样锁不住。
2、原子属性
(1)属性中的修饰符
- nonatomic :非原子属性
- atomic : 原子属性,针对多线程设计的,是默认值。保证同一时间只有一个线程能够写入,但是同一个时间多个线程都可以取值。
- 自旋锁:atomic 本身就有一把锁(自旋锁),保证“单写多读”:单个线程写入,多个线程可以读取。如果发现有其它线程正在锁定代码,线程会用死循环的方式,一直等待锁定的代码执行完成 。自旋锁更适合执行不耗时的代码。
- iOS开发的建议:
- 所有属性都声明为nonatomic,移动设备内存小,atomic虽然相对线程安全,但是消耗资源较多。
- 尽量避免多线程抢夺同一块资源(多个线程访问和修改同一数据)。
- 尽量将加锁、资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力。
3、线程安全
(1)多个线程同时操作一个全局变量是不安全的,使用自旋锁并不是绝对的安全(因为单写多读)。
(2)线程安全:在多个线程进行读写操作时,仍然能够保证数据的正确 。使用互斥锁可以实现,但是消耗性能。
(3)关于主线程(UI线程):几乎所有UIKit
以上是关于iOS开发——多线程的主要内容,如果未能解决你的问题,请参考以下文章