DispatchQueue在Swift中与main.sync崩溃

San*_*ngh 5 event-dispatch-thread ios dispatch-async swift

请向我解释为什么我会遇到这次崩溃?

线程1:EXC_BAD_INSTRUCTION(代码= EXC_I386_INVOP,子代码= 0x0)

在这

DispatchQueue.main.sync {print("sync")}

这是我的代码.

    override func viewDidLoad() {
    super.viewDidLoad()


    print("Start")
    DispatchQueue.main.async {
        print("async")

    }
    DispatchQueue.main.sync {
        print("sync")
    }
    print("Finish")
}
Run Code Online (Sandbox Code Playgroud)

小智 8

@sankalap,Dispatch.main是一个串行队列,它有单个线程来执行所有操作.如果我们在这个队列上调用"sync",它将阻止当前在该线程上运行的所有其他操作,并尝试在内部同步中执行代码块.这导致"死锁".

  • 这是一个僵局.它崩溃是因为GCD检测到这种特殊形式的死锁并中止该程序.如果您重现问题并查看调试器的`_dispatch_sync_wait`反汇编,您将看到消息"LIBDISPATCH的客户端BUG:调用dispatch_sync已在当前线程拥有的队列中". (6认同)

jus*_*ime 7

根据关于在队列上执行的Apple文档dispatch_sync您当前所在的队列会使您的代码崩溃:

调用此函数并以当前队列为目标会导致死锁。

  • 死锁不是崩溃。巨大差距。 (3认同)

Sid*_*tre 5

永远不要在主队列上调用同步功能

如果在主队列上调用sync函数,它将阻塞队列,队列将等待任务完成,但是由于队列已停止,任务甚至无法启动,因此该任务将永远无法完成已经被封锁。这称为死锁

如果两个(或有时更多)项(大多数情况下为线程)被卡住,则它们都陷入彼此的等待对方完成或执行另一项操作的状态。第一个无法完成,因为它正在等待第二个完成。但是第二个无法完成,因为它正在等待第一个完成。

但是您需要小心。想象一下,如果您调用同步并定位您已经在运行的当前队列。这将导致死锁情况。

使用sync可以跟踪使用调度屏障的工作,或者在需要使用操作完成之前,可以使用闭包处理的数据来跟踪工作。

何时使用同步?

当我们需要等到任务完成时。当我们确保某些函数/方法没有被双重调用时,Fe。如果我们有同步,并试图防止它被重复调用,直到完全完成。当您需要等待在不同队列上完成的事情然后才继续在当前队列上工作时

同步与异步

使用GCD,您可以同步或异步分派任务。

任务完成后,同步功能会将控制权返回给调用方。

异步函数立即返回,命令任务完成但不等待它。因此,异步功能不会阻止当前执行线程继续进行下一个功能。