【iOS面试系列-2】多线程中同步、异步和串行、并行之间的逻辑关系(必考,必须掌握)

API-https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/index.html#//apple_ref/doc/uid/TP40008079

 

一、同步、异步和串行、并行

     任务串行执行就是每次只有一个任务被执行任务并发执行就是在同一时间可以有多个任务被执行。

     一个同步函数只在完成了它预定的任务后才返回。一个异步函数,刚好相反,会立即返回,预定的任务会完成但不会等它完成。因此,一个异步函数不会阻塞当前线程去执行下一个函数。
  (来源:http://www.cocoachina.com/industry/20140428/8248.html)
 

  队列分为串行和并行

  任务的执行分为同步和异步

  -------  队列只是负责任务的调度,而不负责任务的执行   ---------

  ------- 任务是在线程中执行的  ---------

  串行队列:任务按照顺序被调度,前一个任务不执行完毕,队列不会调度

  并行队列:只要有空闲的线程,队列就会调度当前任务,交给线程去执行,不需要考虑前面是都有任务在执行,只要有线程可以利用,队列就会调度任务。

  同步执行:不会开启新的线程,任务按顺序执行

  异步执行:会开启新的线程,任务可以并发的执行

  (来源:http://www.cnblogs.com/KongPro/p/5193175.html)

  【注:两人说的有矛盾,一个说队列执行任务,一个说队列不执行任务= =一个说同步异步是返回的问题,一个说同步异步是开不开线程的问题】
  同步(sync)异步(async) 的主要区别在于会不会阻塞当前线程,直到 Block 中的任务执行完毕!
  如果是 同步(sync) 操作,它会阻塞当前线程并等待 Block 中的任务执行完毕,然后当前线程才会继续往下运行。
  如果是 异步(async)操作,当前线程会直接往下执行,它不会阻塞当前线程。
  (原文链接:http://www.jianshu.com/p/0b0d9b1f1f19)
  【第三个人和第一个人的意思差不多】

二、队列

  GCD 提供有 dispatch queues 来处理代码块,这些队列管理你提供给 GCD 的任务并用 FIFO 顺序执行这些任务。这就保证了第一个被添加到队列里的任务会是队列中第一个开始的任务,而第二个被添加的任务将第二个开始,如此直到队列的终点。

  1、串行队列

    唯一能确保的事情是 GCD 一次只执行一个任务,并且按照我们添加到队列的顺序来执行。由于在串行队列中不会有两个任务并发运行。

  放到串行队列的任务,GCD 会 FIFO(先进先出) 地取出来一个,执行一个,然后取下一个,这样一个一个的执行。

  2、并发队列

    在并发队列中的任务能得到的保证是它们会按照被添加的顺序开始执行,任务可能以任意顺序完成,你不会知道何时开始运行下一个任务,或者任意时刻有多少 Block 在运行。再说一遍,这完全取决于 GCD 。

    放到并行队列的任务,GCD 也会 FIFO的取出来,但不同的是,它取出来一个就会放到别的线程,然后再取出来一个又放到另一个的线程。这样由于取的动作很快,忽略不计,看起来,所有的任务都是一起执行的。不过需要注意,GCD 会根据系统资源控制并行的数量,所以如果任务很多,它并不会让所有任务同时执行。

    (来源:http://www.cocoachina.com/industry/20140428/8248.html)

  (原文链接:http://www.jianshu.com/p/0b0d9b1f1f19)

 

三、组合

  1. 串行队列同步执行:综合上面阐述的串行队列的特点 --- 按顺序执行,同步:不会开启新的线程,则串行队列同步执行只是按部就班的one by one执行。
  2. 串行队列异步执行:虽然队列中存放的是异步执行的任务,但是结合串行队列的特点,前一个任务不执行完毕,队列不会调度,所以串行队列异步执行也是one by one的执行
  1. 并行队列同步执行:结合上面阐述的并行队列的特点,和同步执行的特点,可以明确的分析出来,虽然并行队列可以不需等待前一个任务执行完毕就可调度下一个任务,但是任务同步执行不会开启新的线程,所以任务也是one by one的执行
  2. 并行队列异步执行:再上一条中说明了并行队列的特点,而异步执行是任务可以开启新的线程,所以这中组合可以实现任务的并发,再实际开发中也是经常会用到的

  (来源:http://www.cnblogs.com/KongPro/p/5193175.html)

  【个人总结:串行并行区别就是有任务会不会放在别的线程

        同步异步区别是会不会阻塞当前线程

        串行同步:取出一个任务不放进别的线程阻塞当前线程(不开辟新的线程)任务执行完毕任务执行完毕下一个任务

        串行异步:取出一个任务不放进别的线程不阻塞当前线程不等任务执行完成任务执行完毕下一个任务

        并行同步:取出来一个任务可以放在别的线程阻塞当前线程(不开辟新的线程)任务执行完毕不等任务执行完毕下一个任务

        并行异步:取出来一个任务可以放在别的线程不阻塞当前线程不等任务执行完成不等任务执行完成下一个任务

  】

  【所以现在最大的问题是,如果只有一个线程去异步的执行一个并行队列里的任务,会是怎样?感觉上来说,不开线程的话就是同步,一旦叫异步就说明开了线程,所以把这三个人的总结起来才比较合理

 

let queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL)  //创建串行队列

   NSLog("之前 - %@", NSThread.currentThread())

    dispatch_async(queue, { () -> Void in      //异步执行串行队列-开了一个新的线程
        NSLog("sync之前 - %@", NSThread.currentThread())
        dispatch_sync(queue, { () -> Void in   //同步执行串行队列-阻塞当前线程并等待上一个任务执行完毕(而上一个任务就是阻塞的这个)
             NSLog("sync - %@", NSThread.currentThread())
        })
        NSLog("sync之后 - %@", NSThread.currentThread())
   })

  NSLog("之后 - %@", NSThread.currentThread())

  【博客上找来的还是不放心,有时间在书上看到相关的我会再来更新】

--------------------------------------------------------------------------------

现在感觉,任务是先放在队列里,从队列里拿出来同步或者异步执行,当然是不是这样也有待考证。

如果是这样的话,串行队列只能一个一个拿出任务不管你是否阻塞原线程或者有没有开辟新线程,任务都是一个一个执行。

并行队列的话,如果是阻塞原线程的同步执行那也只能一个一个执行,如果是不阻塞原线程再开辟线程的话就可以一起执行了。

疑点在于

1、任务是不是先从队列里拿出并按队列的规则执行,尤其是串行异步(会开辟新的线程么?)和并行同步方面需要注意,他们之间的通信是怎么实现的?

答:在GDC中一个操作是多线程执行还是单线程执行取决于当前队列类型和执行方法,只有队列类型为并行队列并且使用异步方法执行时才能在多个线程中执行。

2、虽然说同步异步的区别在于是否阻塞原线程,但是除了开辟新的线程以外还有方法避免阻塞么?那同步异步的区别是不是就是有没有开辟线程了?

posted @ 2016-09-12 23:16  代我向老师问好  阅读(778)  评论(2编辑  收藏  举报