美文网首页
iOS 多线程 基本概念

iOS 多线程 基本概念

作者: 咖啡豆8888 | 来源:发表于2018-11-29 16:22 被阅读35次

前言

GCD源码地址
GNUStep
(是GNU计划项目之一,他将cocoa库重新开源实现了一遍,不是apple官方文档,但是具有一定的参考价值)
常见的多线程方案一般分为这几种

线程方案

GCD函数

//异步执行任务
dispatch_async(dispatch_get_global_queue(0, 0), ^{
        
    });
//同步执行任务
dispatch_sync(dispatch_get_global_queue(0, 0), ^{
        
    });

同步 异步 串行 并发

  • 同步、异步主要影响:能不能开启新线程。
  • 串行、并发主要影响:任务执行方式,串行一个任务执行完毕之后,在执行下一个。并发多个任务同时执行。

死锁问题

先看一段代码

- (void)viewDidLoad {
    [super viewDidLoad];
     NSLog(@"任务1");
    dispatch_sync(dispatch_get_main_queue(), ^{
         NSLog(@"任务2");
    });   
     NSLog(@"任务3");
}

上面一段代码发生了死锁,为什么呢?原因就是:viewDidLoad是在主队列里面执行的,当执行到任务2的时候,因为是同步任务,所以需要立刻执行任务2,但是队列是先进先出的概念,viewDidLoad本身也是一个任务,他需要执行完任务3之后才能执行任务2,但是任务2需要立即执行,也就是说任务3等待任务2执行完毕执行,任务2有等待任务3执行完毕执行,造成了死锁,程序卡死在任务2处。
死锁原理:使用sync函数往当前串行队列(serial quque)添加任务就会产生死锁

[self performSelector:@selector(test) withObject:nil afterDelay:.0]; 延迟方法

- (void)viewDidLoad {
    [super viewDidLoad];
    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");
}
---------------------------------------------------
2018-11-29 14:09:46.184533+0800 demodemo[88317:5593889] 1
2018-11-29 14:09:46.185962+0800 demodemo[88317:5593889] 3

延迟方法的底层实现是在runloop内部添加定时器来处理任务的,但是子线程默认是没有启动RunLoop的,所以导致方法失效。

dispatch_async(queue, ^{
        NSLog(@"1");
        [self performSelector:@selector(test) withObject:nil afterDelay:.0];
        NSLog(@"3");
        [[NSRunLoop currentRunLoop]addPort:[NSPort new] forMode:NSDefaultRunLoopMode];
        [[NSRunLoop currentRunLoop]runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    });
---------------------------------------------------
2018-11-29 14:20:43.557833+0800 demodemo[88643:5608216] 1
2018-11-29 14:20:43.559215+0800 demodemo[88643:5608216] 3
2018-11-29 14:20:43.559472+0800 demodemo[88643:5608216] 2

启动RunLoop,可以执行延迟函数,因为是延迟函数,需要等待下一次被唤醒的时候处理定时器任务,所以3先被执行。

[self performSelector:@selector(test) withObject:nil] 方法的底层原理是[class msgSend],跟延迟方法是不同的。

从GNUStep可以大致推出延迟方法apple的源码实现是这样的

- (void) performSelector: (SEL)aSelector
          withObject: (id)argument
          afterDelay: (NSTimeInterval)seconds
{
  NSRunLoop     *loop = [NSRunLoop currentRunLoop];
  GSTimedPerformer  *item;

  item = [[GSTimedPerformer alloc] initWithSelector: aSelector
                         target: self
                       argument: argument
                          delay: seconds];
  [[loop _timedPerformers] addObject: item];
  RELEASE(item);
  [loop addTimer: item->timer forMode: NSDefaultRunLoopMode];
}

队列组

dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_async(group, queue, ^{
        for (int i = 0; i<5; i++) {
            NSLog(@"任务1");
        }
    });
    dispatch_group_async(group, queue, ^{
        for (int i = 0; i<5; i++) {
            NSLog(@"任务2");
        }
    });
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"完成");
    });
---------------------------------------------
2018-11-29 15:30:19.442732+0800 demodemo[90541:5689534] 任务2
2018-11-29 15:30:19.442732+0800 demodemo[90541:5689182] 任务1
2018-11-29 15:30:19.443865+0800 demodemo[90541:5689182] 任务1
2018-11-29 15:30:19.443865+0800 demodemo[90541:5689534] 任务2
2018-11-29 15:30:19.444347+0800 demodemo[90541:5689182] 任务1
2018-11-29 15:30:19.444362+0800 demodemo[90541:5689534] 任务2
2018-11-29 15:30:19.444449+0800 demodemo[90541:5689182] 任务1
2018-11-29 15:30:19.444501+0800 demodemo[90541:5689534] 任务2
2018-11-29 15:30:19.444640+0800 demodemo[90541:5689182] 任务1
2018-11-29 15:30:19.445137+0800 demodemo[90541:5689534] 任务2
2018-11-29 15:30:19.446057+0800 demodemo[90541:5689084] 完成

相关文章

  • iOS原理(八)----多线程

    iOS原理(八)----多线程 基本概念 iOS常见的多线程方案有以下四种: pthread:是一套通用的多线程C...

  • iOS多线程之NSThread

    前面总结了多线程基本概念和iOS多线程PThread的使用,下面接着总结iOS多线程的另外一种实现方案NSThre...

  • iOS开发多线程那些事儿

    iOS中的多线程 iOS中多线程实现的多种技术方案: 多线程的两组基本概念 串行(Serial):在固定时间内只能...

  • iOS 多线程

    前言:这可能是史上最全面的一篇iOS 多线程博客了(王婆卖瓜一番?),从多线程的基本概念,进程的概念,引出iOS中...

  • iOS多线程浅汇-实战篇

    一、前言 上一篇文章iOS多线程浅汇-原理篇中整理了一些有关多线程的基本概念。本篇博文介绍的是iOS中常用的几个多...

  • iOS多线程相关面试题

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

  • 多线程之--NSOperation

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

  • iOS多线程之--NSThread

    iOS多线程demo iOS多线程之--NSThread iOS多线程之--GCD详解 iOS多线程之--NSOp...

  • iOS 多线程

    ​ 前言:这可能是史上最全面的一篇iOS 多线程博客了(王婆卖瓜一番?),从多线程的基本概念,进程的概念,引出i...

  • iOS 底层 day19 多线程基本概念 GCD线程死锁总结

    一. 关于多线程中的一些基本概念 1. iOS 中有几种多线程方案有哪几种?分别简述一下。 二. GCD 中的一...

网友评论

      本文标题:iOS 多线程 基本概念

      本文链接:https://www.haomeiwen.com/subject/cppzqqtx.html