1. 程式人生 > >通過GCD中的dispatch_barrier_(a)sync加強對sync中所謂等待的理解

通過GCD中的dispatch_barrier_(a)sync加強對sync中所謂等待的理解

首先解釋下標題裡地括號是什麼意思,GCD有個函式叫dispatch_barrier_async,還有個函式叫dispatch_barrier_sync,這個括號只是用來防止標題取得太長…>_<

對於dispatch_barrier_async可能有的朋友沒用過,不知道它是幹嘛的,簡單地介紹一下下,知道的朋友可以跳過此段。
假設我們原先有6個任務要執行,我們現在要插入一個任務0,這個任務0要在1、2、3都併發執行完了之後才能執行,而4、5、6號任務要在這個任務0結束後才允許併發。大致的意思就跟下面這個圖一樣
這裡寫圖片描述
對於這樣一種需求,很多朋友的第一反應就是用個group就解決了。確實如此,但是系統提供了一種更加簡單地方法,那就是dispatch_barrier_async,我們只要按照前面所述的順序將任務分配到佇列就OK,剩下的都不用管了。dispatch_barrier_async的引數跟dispatch_async一模一樣的。

下面開始講正題
總結前面所說,dispatch_barrier_async是會等待前面提到的任務0結束的,注意這裡是async。說到等待大家必然會想到dispatch_sync,dispatch_sync的任務是序列的,會等待任務結束程式再繼續往下走。那dispatch_barrier是否存在一個sync的方法呢?存在……那麼問題來了……那dispatch_barrier_async和dispatch_barrier_sync的區別在哪呢?如果沒有區別的話蘋果何必搞出2個函式呢,區別必然是有的。

先貼上程式碼,程式碼非常簡單,就是按照之前提的需求寫的。
這裡寫圖片描述
barrier裡給了一個比較費時的操作便於看清楚

給的圖裡寫的是dispatch_barrier_sync,因為我們需要先看看我們熟悉的等待——sync是什麼效果,直接跑起來
這裡寫圖片描述
可以看到,確實是1、2、3號任務併發執行完了,然後再執行的我們的0號任務,再併發執行的4、5、6號任務,當然,point3和barrier之間是有明顯停頓的,截圖無法表現。對於這個輸出,應該是意料之中的。截下來,我們來看看async的效果

程式碼進行一點點修改,dispatch_barrier_sync改成dispatch_barrier_async。我這裡先把aaa、bbb的輸出隱藏掉。改完程式碼可以直接跑起來,我們一起看看結果
這裡寫圖片描述
好像除了aaa、bbb之外其它的都跟上面sync的情況一模一樣(當然,併發的順序無法控制),而且point3和barrier之間同樣有明顯停頓,看來,這個dispatch_barrier_async確實會等待它的任務0執行完。

既然這樣那dispatch_barrier_async和dispatch_barrier_sync究竟有什麼區別呢?我們把aaa、bbb的輸出開啟看看就知道了。
這裡寫圖片描述
區別很明顯,跟sync的情況相比,aaa、bbb的輸出位置完全不同,async的時候aaa的輸出在任務0結束之前,sync的aaa輸出在任務0結束之後。

好了,說到這應該差不多能想通了,我們開始總結
dispatch_barrier_sync和dispatch_barrier_async的共同點:
1、都會等待在它前面插入佇列的任務(1、2、3)先執行完
2、都會等待他們自己的任務(0)執行完再執行後面的任務(4、5、6)

dispatch_barrier_sync和dispatch_barrier_async的不共同點:
在將任務插入到queue的時候,dispatch_barrier_sync需要等待自己的任務(0)結束之後才會繼續程式,然後插入被寫在它後面的任務(4、5、6),然後執行後面的任務
而dispatch_barrier_async將自己的任務(0)插入到queue之後,不會等待自己的任務結束,它會繼續把後面的任務(4、5、6)插入到queue

所以,dispatch_barrier_async的不等待(非同步)特性體現在將任務插入佇列的過程,它的等待特性體現在任務真正執行的過程。