代码之家  ›  专栏  ›  技术社区  ›  jeremyabannister

Swift-如何防止DispatchQueues在同一线程上执行?

  •  0
  • jeremyabannister  · 技术社区  · 5 年前

    我最近一直在学习线程和调度队列,并遇到了一个大问题。我听过很多次GCD 没有保证 给定的工作块可以在哪个线程上执行。大多数情况下,这是一个有用的层次抽象。然而,我碰到了一个错误,我仍然不知道原因,但这使我意识到,在我看来,这方面的GCD的潜在陷阱。

    例子:

    let queue1 = DispatchQueue(label: "one")
    let queue2 = DispatchQueue(label: "two")
    queue1.sync {
        let importantValue1 = "importantValue1"
        let importantValue2 = queue2.sync {
            return "importantValue2"
        }
        print("did important work, got values", importantValue1, importantValue2)
    }
    

    我的问题是,我是否至少保证队列不会在同一线程上执行?从我所看到的情况来看,我似乎没有这个保证。但是,没有它,我不是一直处于僵局的危险之中吗?在上面的示例中,如果两个队列都在线程7上执行,会发生什么情况?打电话给 queue2.sync

    0 回复  |  直到 5 年前
        1
  •  0
  •   gnasher729    5 年前

    后台队列中的任务永远不会阻止后台队列中的其他任务运行,因此,虽然您可以获得死锁,但在同一线程上执行的队列不会导致死锁。

    另一方面,在另一个队列上同步运行代码是毫无意义的。

        2
  •  0
  •   Rob Napier    5 年前

    在大多数情况下,我会 这两个块在同一个队列上运行。事实上,让我们看看:

    import Foundation
    
    let queue1 = DispatchQueue(label: "one")
    let queue2 = DispatchQueue(label: "two")
    queue1.sync {
        let importantValue1 = "importantValue1"
        print(Thread.current)  // Print the current queue
        let importantValue2: String = queue2.sync {
            print(Thread.current) // Print the current queue
            return "importantValue2"
        }
        print("did important work, got values", importantValue1, importantValue2)
    }
    
    <NSThread: 0x6000023b2900>{number = 1, name = main}
    <NSThread: 0x6000023b2900>{number = 1, name = main}
    did important work, got values importantValue1 importantValue2
    

    是的,在我的例子中,两者都是在主线程上运行的,正如您通常希望它们运行的那样。在调用时,通常没有理由强制执行切换线程的大量开销 .sync . 当前线程在块完成之前不能执行任何操作,因此只要没有任何限制(例如,提交到主队列的块),它就可以在当前线程上运行该块 必须 在主线程上运行)。

    .同步