多线程题目解析

- (void)testTimer { // mainThread
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_sync(queue, ^{
        NSLog(@"1");

        dispatch_sync(queue, ^{
           [self performSelector:@selector(log2) withObject:nil afterDelay:0];
        });

        dispatch_async(queue, ^{
            [self performSelector:@selector(log2) withObject:nil afterDelay:0];
        });
        NSLog(@"3");
    });
}

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

在技术群中看到上面这道题,问输出结果是什么?

仔细看了一下,感觉挺有意思的,仅以记录

下面来解析一下这道题都考了那些东西

1、队列与线程

2、同步与异步

3、死锁的触发条件

4、performSelector:withObject:afterDelay:方法

5、线程保活

先从第一点看

I. 队列与线程

iOS中有四种队列,串行队列、并发队列、主线程队列、全局队列。

主队列是一个特殊的串行队列,主队列的任务都在主线程来执行,专门负责调度主线程度的任务,是无法开辟新的线程。

全局队列是一个特殊的并发队列。

注意,不要认为串行队列中的所有任务都在同一个线程中执行,串行队列中的异步任务,可能会开启新线程去执行。

II. 同步与异步

同步(sync):任务一个接着一个,前一个没有执行完,后面不能执行,没有创建新线程的能力。

异步(async):开启多个新线程,任务同一时间可以一起执行。异步有开启新线程的能力,但是不一定会开启新线程(在主队列上就不会开新线程)。严格来说,异步才有多线程的概念,是多线程的代名词。

III. 死锁

死锁的触发条件是 在某一个串行队列中,同步的向这个串行队列中添加任务。

queue是并发队列,所以最外层block是不会触发死锁的,并发队列中的所有任务可以同时执行,所以在这个队列上执行的任务也不会触发死锁。然后同步block是不会开辟线程的,所以这个block中依然是main thread,但是是在global_queue上处理的,所以会输出1

紧跟着又是一个同步任务,所以这个block中也是在主线程中触发的。

III. performSelector:withObject:afterDelay: 这个方法是一个延迟任务,会在当前线程的runloop中添加一个定时器,时间到了才会执行selector中的任务。

第一个方法是在主线程中触发的,主线程创建的时候会默认创建对应的runloop,所以这个方法对应的sel是会触发的,但是这个方法是个延迟任务,方法会晚一点点触发。

dispatch_async(queue, ^{
   [self performSelector:@selector(log2) withObject:nil afterDelay:0];
});

这第二个方法是在当前队列添加的异步任务,会开辟一个子线程来执行任务,但子线程创建的时候,默认是不会创建对应的runloop的,只有用到的时候才会自动创建,当然如果线程中并没有任何事件(source、timer、observer)的话,也不会成功的开启。所以 异步任务会触发,但是这个延迟任务sel是不会触发的,

所以这道题的输出结果是:132

针对死锁做一点延伸:

死锁的触发条件是 在某一个串行队列中,同步的向这个串行队列中添加任务。

1、只会发生在串行队列。并行队列任务是同步执行的,不会阻塞当前线程

2、只会发生在添加同步任务。异步任务会开辟新的线程,不会阻塞当前线程

问:向主线程的串行队列中添加同步任务一定会触发死锁吗?

dispatch_queue_t queue = dispatch_queue_create(@"serial.queue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue,^(void){
  NSLog(@"1");
});
NSLog(@"2");

答案是不一定啊,如上面代码,2是在主线程的主队列上执行输出的,而1的输出任务,是添加到串行队列serial.queue上的。并不会阻塞主线程,所以会立刻执行串行队列serial.queue上的任务,然后再去执行主队列上的任务,所以输出是:12

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值