多线程

多线程

基本概念

1
2
3
4
1. 进程
进程是指在系统中正在运行的一个应用程序。每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内。
2. 线程
1个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程),线程是进程的基本执行单元,一个进程(程序)的所有任务都在线程中执行。

主线程

  1. 什么是主线程
  • 程序运行后, 系统默认开启的线程, 称为”主线程”或”UI线程”
  1. 主线程的主要作用
  • 显示/刷新UI界面
  • 处理UI事件
  1. 主线程的使用注意
  • 不要把耗时操作放到主线程中
  • 耗时操作会卡住主线程, 严重影响UI流畅度

耗时操作的执行
将耗时操作放在子线

iOS中多线程的实现

技术方案 简介 语言 线程生命周期 使用频率
pthread x C 程序员管理 几乎不用
NSThread x OC 程序员创建 偶尔使用
GCD x C 自动管理 经常使用
NSOperation x OC 自动管理 经常使``

线程的状态

互斥锁

多线程安全隐患

  • 资源共享
    • 1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源
    • 比如多个线程访问同一个对象、同一个变量、同一个文件
  • 当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题

互斥锁解决安全隐患

互斥锁使用格式

1
2
3
@synchronized(锁对象) {
// 需要锁定的代码
}

互斥锁的使用前提:多条线程抢夺同一块资源
互斥锁的优缺点

  • 优点:能有效防止因多线程抢夺资源造成的数据安全问题
  • 缺点:需要消耗大量的CPU资源

互斥锁的注意点

  • 锁定1份代码只用1把锁,用多把锁是无效的

相关专业术语:线程同步

线程同步的意思是:多条线程在同一条线上执行(按顺序地执行任务)
互斥锁,就是使用了线程同步技术

pthread


1
pthread_create(pthread_t *restrict, const pthread_attr_t *restrict, void *(*)(void *), void *restrict)

NSThread


基本使用

在NSThread中,一个线程就是一个NSThread对象

1
2
3
4
// 创建线程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(speak) object:nil];
// 启动线程
[thread start];

线程其他用法

1
2
3
+ (NSThread *)mainThread; // 获得主线程
- (BOOL)isMainThread; // 是否为主线程
+ (BOOL)isMainThread; // 是否为主线程

创建线程的其他方式

上述2种创建线程⽅方式的优缺点

  • 优点:简单快捷
  • 缺点:⽆无法对线程进⾏行更详细的设置
1
2
3
4
5
6
7
// 创建线程后⾃自动启动线程
[NSThread detachNewThreadSelector:@selector(run)
toTarget:self withObject:nil];

// 隐式创建并启动线程
[self performSelectorInBackground:@selector(run)
withObject:nil];

控制线程状态

1
2
3
4
5
6
7
8
// 启动线程
- (void)start;
// 阻塞(暂停)线程,进⼊入阻塞状态
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
+ (void)sleepUntilDate:(NSDate *)date;

// 强制停⽌止线程,进⼊入死亡状态
+ (void)exit;
  • 线程启动后,进⼊就绪状态 -> 运⾏行状态。
  • 当线程任务执⾏行完毕,⾃自动进⼊入死亡状态
  • 一旦线程停⽌止(死亡)了,就不能再次开启任务

线程间通信

线程间通信的体现

  • 1个线程传递数据给另1个线程
  • 在1个线程中执行完特定任务后,转到另1个线程继续执行任务

线程间通信常用方法

1
2
3
4
5
// 在主线程中执行方法
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;

// 在指定线程中执行方法
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;

还有一种方式: 利用NSPort