斯威夫特陷入僵局

  • 本文关键字:陷入僵局 swift
  • 更新时间 :
  • 英文 :


有两个代码片段。 1.

let queue = DispatchQueue(label: "---", qos: .default)
queue.async {
  print("11--(Thread.current)")
  queue.sync {
    print("22--(Thread.current)")
  }
}
let queue1 = DispatchQueue(label: "+++", qos: .default)
let queue = DispatchQueue(label: "---", qos: .default)
queue.async {
  print("11--(Thread.current)")
  queue1.sync {
    print("22--(Thread.current)")
  }
}

第一个会deadlock,第二个不会deadlock.
在第一个代码中,两次打印的结果是相同的线程,所以会导致死锁;在第二个代码中,同一个线程打印两次,为什么不造成死锁呢?

你说:

在第一个代码中,两次打印的结果是相同的线程,因此会导致死锁;

是的,这段代码实际上是在说

  1. 将此代码调度到串行队列,在该队列上的其他所有内容完成后运行它;
  2. 因为它使用了sync,它还告诉当前队列等待并因此阻止这个串行队列,直到这个调度的代码运行;
  3. 调度的代码永远无法运行,因为它被调度到的队列被阻止。

僵局。

考虑:


let queue = DispatchQueue(label: "---")
queue.async {
print("11--(Thread.current)")
queue.sync {
print("33--(Thread.current)")   // run after 22, but it can’t because `sync` to same serial queue deadlocks us
}
print("22--(Thread.current)")
}

你继续说:

。在第二个代码中,同一个线程被打印两次,那么为什么不导致死锁呢?

这是不同的,因为它说"阻止当前串行队列,直到调度到第二个串行队列的代码完成"。 即,调度到第二个队列的代码不必等待调度到第一个队列的所有代码完成。在第二个队列上运行的代码恰好只在同一线程上运行,因为作为优化,GCD 足够聪明,可以确定它可以只在当前线程上运行代码,因为该线程无论如何都会被sync调用阻止。(请参阅sync文档中的注释。这种 GCD 优化只是消除了不必要的上下文切换。

考虑:

let queue1 = DispatchQueue(label: "1")
let queue2 = DispatchQueue(label: "2")
queue1.async {
print("11--(Thread.current)")
queue2.sync {
print("22--(Thread.current)")   // run on separate queue after 11 and before 33; no deadlock, even though it may run on same thread as part of GCD optimization
}
print("33--(Thread.current)")
}

队列不是线程。

生成的线程可能被不同的队列(重新)用来执行其计划的工作.
这是第二个示例中发生的情况。

sync函数确保队列中的同步.
并不是说这段代码将在特定 tread.
在您的示例中,绝对没有理由在不同的线程上执行。

第一个示例中的死锁来自您在当前运行的队列上同步执行的事实.
它与线程无关.
它不会发生在第二个示例中,因为队列不同(例如,使用不同的互斥锁进行同步),即使使用相同的线程也是如此。

最新更新