0
点赞
收藏
分享

微信扫一扫

串行队列中任务的同步和异步执行

小龟老师 2021-09-25 阅读 70

本人有若干成套学习视频, 可试看! 可试看! 可试看, 重要的事情说三遍 包含Java, 数据结构与算法, iOS, 安卓, python, flutter等等, 如有需要, 联系微信tsaievan.

  • 串行队列同步执行
        let serialQueue = DispatchQueue(label: "dispatch_demo.tsaievan.com")
        let mainQueue = DispatchQueue.main
        let sAdd = String(format: "%p", serialQueue)
        let mAdd = String(format: "%p", mainQueue)
        serialQueue.sync {
            print("\(Thread.current)========1==== sAdd = \(sAdd)===== mAdd = \(mAdd)")
        }
        print("\(Thread.current)========2")
        serialQueue.sync {
            print("\(Thread.current)========3")
        }
        print("\(Thread.current)========4")

如上图所示, serialQueue是我创建的串行队列, 而mainQueue是主队列, 当serialQueue这个串行队列中的任务同步执行的时候, 是不创建新的线程的, 那么任务会在当前线程执行, 即主线程执行, 此时, 主线程中就有serialQueuemainQueue两个队列的任务.

下图为打印结果:

<NSThread: 0x60c00006c4c0>{number = 1, name = main}========1==== sAdd = 0x608000144410===== mAdd = 0x1057a1e80
<NSThread: 0x60c00006c4c0>{number = 1, name = main}========2
<NSThread: 0x60c00006c4c0>{number = 1, name = main}========3
<NSThread: 0x60c00006c4c0>{number = 1, name = main}========4
  • 串行队列异步执行
        serialQueue.async {
            print("\(Thread.current)========1==== sAdd = \(sAdd)===== mAdd = \(mAdd)")
        }
        print("\(Thread.current)========2")
        serialQueue.async {
            print("\(Thread.current)========3")
        }
        print("\(Thread.current)========4")

串行队列异步执行会开新的线程, 但只会开一条新的线程.
上面的代码, 情况是这样的, serialQueue放到子线程中去执行了,

print("\(Thread.current)========2")
print("\(Thread.current)========4")
这两句代码还是在主线程/主队列中执行的

serialQueue虽然在子线程中执行, 但也遵循FIFO(先进先出)的策略, 所以:

print("\(Thread.current)========1==== sAdd = \(sAdd)===== mAdd = \(mAdd)")
这个任务一定是先于
print("\(Thread.current)========3")这个任务的

打印顺序如下:

<NSThread: 0x600000064c00>{number = 1, name = main}========2
<NSThread: 0x60400026d980>{number = 3, name = (null)}========1==== sAdd = 0x60c000158cb0===== mAdd = 0x10e704e80
<NSThread: 0x600000064c00>{number = 1, name = main}========4
<NSThread: 0x60400026d980>{number = 3, name = (null)}========3

当然, 也有可能是(2134) (1234)(1243)(2143)(2413)等

  • 串行异步中嵌套同步
        print("\(Thread.current)========1")
        serialQueue.async {
            print("\(Thread.current)========2")
            serialQueue.sync {
                print("\(Thread.current)========3")
            }
            print("\(Thread.current)========4")
        }
        print("\(Thread.current)========5")

这样的情况会造成 死锁

首先, serialQueue异步执行, 开启了新的线程, 在这个serialQueue串行队列中有一任务, 见下图:


我们把整个这个任务叫做任务A

任务A现在在serialQueue串行队列中是排在前面的

然而, 在serialQueue串行队列中, 还有一个任务B

所以A和B在串行队列中的顺序如下图所示:


也就是A执行完了再执行B, 但是B是同步的, 也就是线程阻塞的, 必须等到B执行完了A任务才能执行完, 所以A在等待B执行完毕, 但B又在等待A执行完毕, 这样就造成了死锁, B永远无法执行, A也无法执行完毕

所以打印结果是:

<NSThread: 0x60c000076240>{number = 1, name = main}========1
<NSThread: 0x60c000076240>{number = 1, name = main}========5
<NSThread: 0x60c00007c7c0>{number = 3, name = (null)}========2

然后程序崩溃!

  • 串行同步中嵌套异步
        print("\(Thread.current)========1")
        serialQueue.sync {
            print("\(Thread.current)========2")
            serialQueue.async {
                print("\(Thread.current)========3")
            }
            print("\(Thread.current)========4")
        }
        print("\(Thread.current)========5")

这种情况是不会造成死锁的


由于红色方框内的任务, 你可以看成是任务A, 任务A是分配在主线程中的,


而蓝色方框的任务B是分配在子线程中的, 所以不会造成线程上的阻塞

所以主线程的顺序一定是, 1,2,4,5
而打印3这个任务由于处于子线程, 所以会放在打印2之后的任意位置,
所以可能的顺序有12345,12435,12453

实际打印几乎全部是12453, 具体原因不知道, ?

PS. 本人有若干成套学习视频, 包含Java, 数据结构与算法, iOS, 安卓, python, flutter等等, 如有需要, 联系微信tsaievan.

举报

相关推荐

0 条评论