1.线程相关概念
进程是指在系统中正在运行的一个应用程序
进程和进程之间时相互独立的:在内存当中都有属于自己的一段内存空间
线程:一个进程可以有多个线程组成(1个进程至少要有一个线程(主线程)
多线程的作用:解决程序阻塞问题
提升程序到执行效率
单核cpu的情况下,多线程时快速的在多个线程之间切换
如果线程非常多的话,cpu在多个线程之间来回切换,会降低程序的性能
多线程 优点:
- 能适当提高程序的执行效率
- 能适当提高资源的利用率(cpu,内存)
- 线程上的任务执行完成后,线程会自动销毁
- 缺点
- 开启线程需要占用一定的内存空间(默认情况下,每一个线程都占512KB)
- 如果开启大量的线程,会占用大量的内存空间,降低程序的性能
- 线程越多,cpu在调用线程上的开销就越大
- 程序设计更加复杂,比如多线程的数据共享、线程间的通信
2.oc中线程的创建方式:
- 方式1
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(demo:) object:nil];
[thread start];
- 方式2
[NSThread detachNewThreadSelector:@selector(demo:) toTarget:self withObject:nil];
- 方式3
[self performSelectorInBackground:@selector(demo:) withObject:nil];
4. 线程的属性:
线程名称:设置线程名称可以当线程执行的方法内部出现异常的时候纪录 异常信息
线程优先级:
内核调度的时候,较高的优先级线程比较低的线程具有更多的机会调度
5.线程安全问题:
当多线程同时访问共享资源的时候,会造成数据安全问题
解决:加锁
1.互斥锁:
oc中互斥锁:@synchronized(锁对象) { 执行的代码块 }
oc中加锁是加在代码块上,不是变量,或共享资源上
oc中互斥锁原理:
- 互斥锁原理
- 每一个对象(NSObject)内部都有一个锁(变量),当有线程要进入synchronized到代码块中会先检查对象的锁是打开还是关闭状态,默认锁是打开状态(1),如果是线程执行到代码块内部 会先上锁(0)。如果锁被关闭,再有线程要执行代码块就先等待,直到锁打开才可以进入。
线程执行到synchronized
i. 检查锁状态 如果是开锁状态(1)转到ii 如果上锁(0)转到v
ii. 上锁(0)
iii. 执行代码块
iv. 执行完毕 开锁(1)
v. 线程等待(就绪状态)
加锁后程序执行的效率比不加锁的时候要低,因为要线程要等待锁,但是锁保证了多个线程同时操作全局变量的安全性
- 属性中的修饰符
- nonatomic 非原子属性
- atomic 原子属性(线程安全),针对多线程设计的,默认值
保证同一时间只有一个线程能够写入(但是同一个时间多个线程都可以取值)
单写多读:单个线程写入,多个线程可以读取
atomic 本身就有一把锁(自旋锁)
- nonatomic和atomic对比
- atomic:线程安全,需要消耗大量的资源
- nonatomic:非线程安全,适合内存小的移动设备
- 互斥锁
- 如果发现其他线程正在执行锁定代码,线程会进入休眠(就绪状态),等其它线程时间片到打开锁后,线程会被唤醒(执行)
- 自旋锁
- 如果发现有其它线程正在锁定代码,线程会用死循环的方式,一直等待锁定的代码执行完成 自旋锁更适合执行不耗时的代码
***
- 几乎所有UIKit类库提供的类都是线程不安全的,所有更新UI的操作都在主线程上执行
- 所有包含NSMutable的类都是线程不安全的