這感覺就像是一種過度複雜的思維方式,而且有很多描述中的小細節並不完全正確。具體來說,「它立即發生在當前線程上」是不正確的。
首先,讓我們退一步:dispatch_async
和dispatch_sync
之間的區別只是是否當前線程等待與否。但是當你將一些東西發送到串行隊列時,你應該總是想象它在GCD自己選擇的單獨的工作線程上運行。是的,作爲優化,有時dispatch_sync
將使用當前的線程,但您無法保證這一事實。
其次,當你討論dispatch_sync
時,你會說「立即」運行。但決不立刻。如果某個線程對某些串行隊列執行dispatch_sync
,則該線程將阻塞,直到(a)該串行隊列上當前正在運行的任何塊完成; (b)該串行隊列的任何其他排隊塊運行並完成; (c)顯然,線程A本身調度的塊運行並完成。
現在,當您使用串行隊列進行同步時,對內存中的某個對象進行某種線程安全訪問,通常該同步過程非常快,因此等待的線程通常會被阻塞的時間可以忽略不計其派出的區塊(以及任何先前分派的區塊)完成。但總的來說,它會立即運行,這是誤導性的。 (如果它總是可以立即運行,那麼你不需要隊列來同步訪問)。
現在關於「關鍵區域」你的問題的會談,而我假設你正在談論的一些代碼位,爲了保證線程安全或其他一些原因類似,必須同步。因此,在運行此代碼以進行同步時,唯一的問題是dispatch_sync
vs dispatch_async
是當前線程是否必須等待。例如,一種常見模式是,可能會向某個模型寫入dispatch_async
(因爲在繼續之前不需要等待模型更新),但dispatch_sync
會讀取某個模型(因爲您顯然不想繼續直到返回讀取值)。
該同步/異步模式的進一步優化是讀寫器模式,其中併發讀取是允許的,但併發寫入不是。因此,您將使用併發隊列dispatch_barrier_async
寫入(實現類似於寫入的串行行爲),但使用dispatch_sync
讀取(享受與其他讀取操作相關的併發性能)。
來源
2017-02-04 01:18:38
Rob
關鍵區域是關鍵部分的另一個名稱:https://en.wikipedia.org/wiki/Critical_section –
是的,這就是我認爲你的意思。在iOS中我們稱之爲需要「同步」。請參見[線程編程指南:同步](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#//apple_ref/doc/uid/10000057i-CH8-SW1 )。但是,這早於GCD,這在[併發編程指南:消除基於鎖的代碼](https://developer.apple.com/library/content/documentation/General/Conceptual/ConcurrencyProgrammingGuide/ThreadMigration/ThreadMigration.html#//apple_ref/DOC/UID/TP40008091-CH105-SW3)。 – Rob
是的。所以我立即說出了一些sl sl,但我做了正確的事情。幸運的是,我認爲我可以簡化爲Android實現的1個消息隊列,而不是圍繞核心數據通知構建的架構使事情變得更容易。 –