iOS底层原理iOS开发你需要知道的

小码哥底层原理笔记:多线程

2020-07-09  本文已影响0人  chilim

多线程方案:

多线程方案比较

比较常用的是GCD,是直接用Block去写代码的。使代码比较紧凑。

GCD常用函数

同步执行任务:dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
异步执行任务:dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
控制任务的执行顺序:
dispatch_barrier_async:栅栏函数,它等待所有位于barrier函数之前的操作执行完毕后执行,并且在barrier函数执行之后,barrier函数之后的操作才会得到执行。并且需要在异步并发队列才有效。
dipatch_group:线程组,可以实现A、B、C、任务并发执行,完了之后再通知执行D任务。

各种多线程队列的执行效果:

多线程各队列执行效果
注意:全局队列也是一个并发队列,主队列是一个串行队列。同步和异步主要影响能不能开启新线程

多线程的安全隐患:当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题。

面试题

NSLog(@"执行任务1");
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_sync(queue, ^{
        NSLog(@"执行任务2");
    });
    NSLog(@"执行任务3");

以上代码在主线程中执行会产生死锁。dispatch_sync 会立马在当前线程执行任务

NSLog(@"执行任务1");
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_async(queue, ^{
        NSLog(@"执行任务2");
    });
    NSLog(@"执行任务3");

以上代码在主线程执行不会产生死锁。dispatch_async并不会立马执行。打印顺序是任务1、任务3、任务2。

NSLog(@"执行任务1");
    dispatch_queue_t queue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_SERIAL);
    dispatch_async(queue, ^{//block01
       NSLog(@"执行任务2");
        dispatch_sync(queue, ^{//block02
            NSLog(@"执行任务3");
        });
        NSLog(@"执行任务4");
    });
    NSLog(@"执行任务5");

以上代码在主线程执行会产生死锁。会生成一个新线程,这个新线程是串行执行任务,先执行block01,然后再执行block02,由于block01在前面,要执行完block01才能执行block02,而block02又必须要等block01执行完,这样就互相等待,产生死锁。

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_async(queue, ^{
        NSLog(@"1");
        [self performSelector:@selector(test) withObject:nil afterDelay:0];
        NSLog(@"3");
    });

- (void)test{
    NSLog(@"2");
}

以上代码只打印了1和3。因为performSelector:withObject:afterDelay方法的本质是往RunLoop里面添加了一个定时器。由于在这个子线程中没有启动RunLoop,所以test方法并不会执行。凡是有afterDelay的方法都是在RunLoop实现的。如果没有afterDelay比如performSelector:withObject:方法则是通过objc_msgSend执行。

死锁总结

使用sync同步执行往当前串行队列中添加任务,这样就会产生死锁

上一篇 下一篇

猜你喜欢

热点阅读