多线程系列

--------------------多线程--------------------

你理解的多线程?

iOS中的常见多线程方案

技术方案 简介 语言 生命周期 使用频率
pthread 一套通用的多线程API
适用于Unix\Linux\Windows等系统
跨平台\可移植
使用难度大
C 程序员管理 几乎不用
NSThread 使用更加面向对象
简单易用,可直接操作线程对象
OC 程序员管理 偶尔使用
GCD 旨在替代NSThread等线程技术
充分利用设备的多核
C 自动管理 经常使用
NSOperation 基于GCD(底层是GCD)
比GCD多了一些更简单实用的功能
使用更加面向对象
OC 自动管理 经常使用

下面打印结果

- (void)viewDidLoad{
    [super viewDidLoad];
    dispatch_queue_t que = dispatch_get_global_queue(0, 0);
    dispatch_async(que, ^{
        NSLog(@"1");
        [self performSelector:@selector(test) withObject:nil afterDelay:0];
        NSLog(@"3");
    });
}
- (void)test{
    NSLog(@"2");
}

打印结果为1,3.原因:
performSelector:withObject:afterDelay:的本质是往Runloop中添加定时器
子线程默认没有启动Runloop

- (void)test{
    NSLog(@"2");
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    NSThread *thread = [[NSThread alloc] initWithBlock:^{
        NSLog(@"1");
    }];
    [thread start];
    [self performSelector:@selector(test) onThread:thread withObject:nil waitUntilDone:YES];
}

会crash,因为新开的NSThread运行完之后就不可用了.除非在运行的时候开启它自己的NSRunLoop.那个线程会一直在那跑.

NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];
        [currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];

GCD常用函数

同步:dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
异步:dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

并发队列:可以让多个任务并发(同时)执行,并发功能只有在异步(dispatch_async)函数下才有效
串行队列:让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)

同步、异步、并发、串行

同步和异步主要影响:能不能开启新的线程:
同步:在当前线程中执行任务,不具备开启新线程的能力
异步:在新的线程中执行任务,具备开启新线程的能力

并发和串行主要影响:任务的执行方式:
并发:多个任务并发(同时)执行
串行:一个任务执行完毕后,再执行下一个任务

并发队列 手动创建的串行队列 主队列
同步 没有开启新线程
串行执行任务
没有开启新线程
串行执行任务
没有开启新线程
串行执行任务
异步 有开启新线程
并发执行任务
有开启新线程
串行执行任务
没有开启新线程
串行执行任务

使用sync函数往当前串行队列中添加任务,会卡住当前的串行队列(产生死锁)

队列组可使用在有任务依赖的地方:dispatch_group_t

多线程的数据安全

多线程的安全主要是通过在写的时候来加锁确保数据的安全,一般情况下都为多读单写,读写分离,读和写不可以同步进行.下面是关于锁的介绍:
自旋锁: 等待锁的线程会处于忙等(busy-wait)状态,一直占用着CPU资源

  1. 目前已经不再安全,可能会出现优先级反转问题
  2. 如果等待锁的线程优先级较高,它会一直占用着CPU资源,优先级低的线程就无法释放锁
  3. 需要导入头文件#import

互斥锁: 从底层调用看,等待os_unfair_lock锁的线程会处于休眠状态,并非忙等

  1. 需要导入头文件#import
  2. 用于取代不安全的OSSpinLock ,从iOS10开始才支持

递归锁: 递归锁有一个特点,就是同一个线程可以加锁N次而不会引发死锁。但是需要成对出现

Foundation系列:
NSLock是对mutex普通锁的封装,NSRecursiveLock也是对mutex递归锁的封装,API跟NSLock基本一致,NSCondition是对mutex和cond的封装,NSConditionLock是对NSCondition的进一步封装,可以设置具体的条件值

你都用过哪些锁(线程同步方案)?结合实际谈谈你是怎样使用的?
性能从高到低:
os_unfair_lock(互斥锁)
OSSpinLock(自旋锁)
dispatch_semaphore(信号量,设置为1代表只允许1条线程访问资源,保证线程同步)
pthread_mutex(互斥锁,等待锁的线程会处于休眠状态.#import )
dispatch_queue(DISPATCH_QUEUE_SERIAL)(串行队列,实现线程同步)
NSLock
NSCondition
pthread_mutex(recursive)
NSRecursiveLock
NSConditionLock
@synchronized(是对mutex递归锁的封装)

你可能感兴趣的:(多线程系列)