性能从高到低排序
os_unfair_lock iOS //10 之后才可以使用
OSSpinLock // iOS10 之后不建议使用
dispatch_semaphore // 我个人比较喜欢使用
pthread_mutex // 我个人比较喜欢使用
dispatch_queue(DISPATCH_QUEUE_SERIAL)
NSLock // 封装 pthread_mutex
NSCondition
pthread_mutex(recursive) // 递归锁
NSRecursiveLock
NSConditionLock
@synchronized 可以直接在GNU 里面看相关的代码
多线程学习
技术方案 | 简介 | 语言 | 线程生命周期 | 使用频率 |
---|---|---|---|---|
pthread | 一套通用的多线程API 适用于Unix\Linux\Windows等系统 跨平台\可移植 使用难度大 | C | 程序员管理 | 几乎不用 |
NSThread | 使用更加面向对象 简单易用,可直接操作线程对象 | OC | 程序员管理 | 偶尔使用 |
GCD | 旨在替代NSThread等线程技术 充分利用设备等多核 | C | 自动管理 | 经常使用 |
NSOperation | 基于GCD(底层是GCD) 比GCD 多了一些简单实用的功能 实用更加面向对象 | OC | 自动管理 | 经常使用 |
GCD 的常用函数
GCD 队列可以分为2大类
并发队列
可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)
并发功能只能在异步(dispatch_async)函数下才能生效
串行队列
让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)
比较容易混淆的专业术语
同步 异步 并发 串行
同步和异步主要是影响:能不能开启新的线程
同步:在当前线程中执行任务,不具备开启新的线程的能力 dispatch_sync
异步:在新的线程中执行任务,具备开启新线程的能力 dispatch_async
如果放在了主队列,那么只能在主线程执行
并发和串行
并发:多个任务并发(同时)执行 dispatch_get_global_queue(0, 0);
串行:一个任务执行完毕后,再执行下一个任务 dispatch_queue_create("que1", DISPATCH_QUEUE_SERIAL);
同步/异步 | 并发队列 | 手动创建串行队列 | 主队列(特殊的串行队列) |
---|---|---|---|
同步sync | 没有开启新的线程 串行执行任务 | 没有开启新的线程 串行执行任务 | 没有开启新的线程 串行执行任务 |
异步async | 有开启新的线程 并发执行任务 | 有开启新的线程的线程 串行执行任务 | 没有开启新的线程 串行执行任务 |
使用sync 函数往当前串行队列中添加任务,会卡住当前的串行队列(产生死锁)
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"------");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{ // 死锁
NSLog(@"---1---");
NSLog(@"%@", [NSThread currentThread]);
});
NSLog(@"---2---");
}
线程组
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_queue_create("gyule", DISPATCH_QUEUE_CONCURRENT);// 并发
NSLog(@"------");
dispatch_group_async(group, queue, ^{
for (int i = 0; i < 5; i++) {
NSLog(@"任务1-----%@", [NSThread currentThread]);
}
});
dispatch_group_async(group, queue, ^{
for (int i = 0; i < 5; i++) {
NSLog(@"任务2---- - %@", [NSThread currentThread]);
}
});
//等前面的执行完成之后再执行下面的任务
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
for (int i = 0; i < 5; i++) {
// 在主线程执行
NSLog(@"任务3 -----%@", [NSThread currentThread]);
}
});
//等前面的执行完成之后再执行下面的任务 1 2 会并发,12 结束后 4 5 会并发
dispatch_group_notify(group, queue, ^{
for (int i = 0; i < 5; i++) {
NSLog(@"任务4 -----%@", [NSThread currentThread]);
}
});
//等前面的执行完成之后再执行下面的任务
dispatch_group_notify(group, queue, ^{
for (int i = 0; i < 5; i++) {
NSLog(@"任务5 -----%@", [NSThread currentThread]);
}
});
线程同步技术(同步就是协同步调,按预定的先后次序进行)
常用的线程同步技术是:加锁
锁:
锁名字 | 说明 |
---|---|
OSSpinLock | 自旋锁,等待锁的线程会处于忙等(busy-wait)状态,一直占用CPU资源,目前已经不再安全,可能会出现优先级反转问题 |
os_unfair_lock | 用于取代不安全的OSSpinLock从iOS10 以后开始可以使用,从底层看是线程进行休眠,并非忙等 |
pthread_mutex | 互斥锁,等待锁的线程处于休眠状态 |
OSSpinLock
#import <libkern/OSAtomic.h>
@property(nonatomic,assign) OSSpinLock lock; // c 语言使用assign 修饰
- (void)lock1 {
// 初始化锁
OSSpinLock lock = OS_SPINLOCK_INIT;
// 加锁
OSSpinLockLock(&lock);
// 尝试加锁
// bool locked = OSSpinLockTry(&lock);
// 解锁
OSSpinLockUnlock(&lock);
}
os_unfair_lock
#import <os/lock.h>
// 结构体 使用assign
@property (nonatomic, assign) os_unfair_lock lock1;
- (void)lock2 {
// 初始化锁
os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;
// 加锁
os_unfair_lock_lock(&lock);
// 尝试加锁
bool locked = os_unfair_lock_trylock(&lock);
// 解锁
os_unfair_lock_unlock(&lock);
}
pthread_mutex_lock
- (void)lock3 {
// 静态初始化互斥锁
// pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex;
// 初始化属性
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
// /*
// * Mutex type attributes
// */
// #define PTHREAD_MUTEX_NORMAL 0 // 常规锁 默认锁
// #define PTHREAD_MUTEX_ERRORCHECK 1 // 检查锁
// #define PTHREAD_MUTEX_RECURSIVE 2 // 自旋锁
// #define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL
// 递归锁:允许同一个线程对一把锁进行重复加锁
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT);
// 初始化锁
pthread_mutex_init(&mutex, &attr);
// 销毁属性
pthread_mutexattr_destroy(&attr);
// 加锁
pthread_mutex_lock(&mutex);
// 解锁
pthread_mutex_unlock(&mutex);
// 释放锁
pthread_mutex_destroy(&mutex);
}
使用场景 生产者消费者模式,线程依赖 例如 线程1 等待线程2 结束之后才能执行
-(void)lock4{
// 条件锁
pthread_cond_t cont;
pthread_cond_init(&cont,nil);
// 互斥锁属性
pthread_mutexattr_t attr;
// 互斥锁属性初始化
pthread_mutexattr_init(&attr);
// 添加属性 递归锁 允许同一个线程对同一把锁进行多次加锁
/*
* Mutex type attributes
*/
// #define PTHREAD_MUTEX_NORMAL 0 // 正常锁
// #define PTHREAD_MUTEX_ERRORCHECK 1 // 检查锁
// #define PTHREAD_MUTEX_RECURSIVE 2 // 递归锁
// #define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL // 默认锁
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
pthread_mutex_t mutex;
pthread_mutex_init(&mutex,&attr);
pthread_mutex_lock(&mutex);
// 睡觉 放开mutex 这把锁 等待 cont 别人放开
pthread_cond_wait(&cont, &mutex);
// 唤醒 等待 cont的线程
pthread_cond_signal(&cont);
pthread_mutex_unlock(&mutex);
// 释放 互斥锁
pthread_mutex_destroy(&mutex);
// 释放 互斥锁的属性
pthread_mutexattr_destroy(&attr);
// 释放条件
pthread_cond_destroy(&cont);
}
网友评论