簡體   English   中英

DispatchQueue.sync { } 阻塞“線程”或“隊列”

[英]DispatchQueue.sync { } blocks "thread" or "queue"

我很困惑。

下面的代碼肯定會導致死鎖:

// Will execute
DispatchQueue.main.async { // Block 1 
  // Will execute
    DispatchQueue.main.sync { // Block 2
     // Will not be executed
    }
    // Will not be executed
}

因為

  1. 我們在主隊列上 dispatch_async 后,它會將第一個塊提交到主隊列執行
  2. 在某個時刻,系統決定運行 block1
  3. .sync方法阻止“線程/隊列?” <-我的問題
  4. 因為“線程/隊列”被阻塞了,block 2在block 1完成之前無法執行,因為Main queue是一個串行隊列,它串行執行任務,一個不能在另一個完成之前執行

我的問題是: sync會阻塞current thread it's executing on還是current queue (我了解線程和隊列之間的區別)

互聯網上的大多數答案都說它阻塞了線程

  1. if block thread -> 線程被阻塞后,為什么sync { }塊仍然可以執行?

  2. 如果阻塞隊列-> 更有意義? 由於隊列被阻塞,我們不能在其他完成之前執行一個

我發現了一些關於此的討論:

dispatch_sync 內部 dispatch_sync 導致死鎖

DispatchQueue.sync 與 DispatchQueue.async 之間的區別

如果在同一個隊列上調度會發生什么?

您問:

我的問題是:同步會阻塞它正在執行的當前線程還是當前隊列?

它阻塞當前線程。

在處理串行隊列(例如主隊列)時,如果該隊列正在運行其線程被阻塞的某些東西,則在該隊列再次空閑之前,將阻止其他任何東西在該隊列上運行。 串行隊列一次只能使用一個線程。 因此,從任何串行隊列同步調度到自身將導致死鎖。

但是,從技術上講, sync不會阻塞隊列。 它阻塞當前線程。 值得注意的是,在處理並發隊列(例如全局隊列或自定義並發隊列)時,該隊列可以同時利用多個工作線程。 因此,僅僅因為一個工作線程被阻塞,它不會阻止並發隊列在另一個未阻塞的工作線程上運行另一個已調度的項目。 因此,從並發隊列同步調度到自身通常不會死鎖(只要您不耗盡非常有限的工作線程池)。


例如

let serialQueue = DispatchQueue(label: "serial")

serialQueue.async {
    serialQueue.sync {
        // will never get here; deadlock
        print("never get here")
    }
    // will never get here either, because of the above deadlock
}

let concurrentQueue = DispatchQueue(label: "concurrent", attributes: .concurrent)

concurrentQueue.async {
    concurrentQueue.sync {
        // will get here as long as you don't exhaust the 64 worker threads in the relevant QoS thread pool
        print("ok")
    }
    // will get here
}

您問:

  1. if block thread -> 線程被阻塞后,為什么sync { }塊仍然可以執行?

正如您在自己的代碼片段中指出的那樣, sync不會執行(在串行隊列場景中)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM