GCD之dispatch_async;dispatch_sync;dispatch_async_f;dispatch_sync_f

一稀轨、概念與類型

對(duì)于GCD來說填物,所有的執(zhí)行都放到隊(duì)列中(queue)冰单,隊(duì)列的特點(diǎn)是FIFO(先提交的先執(zhí)行)幌缝。
GCD的隊(duì)列分為幾種,主隊(duì)列(main),全局隊(duì)列(global),用戶創(chuàng)建隊(duì)列(create)
對(duì)于全局隊(duì)列诫欠,默認(rèn)有四個(gè)涵卵,分為四個(gè)優(yōu)先級(jí)
#define DISPATCH_QUEUE_PRIORITY_HIGH 2
#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0
#define DISPATCH_QUEUE_PRIORITY_LOW (-2)
#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN

DISPATCH_QUEUE_PRIORITY_HIGH :優(yōu)先級(jí)最高浴栽,在default,和low之前執(zhí)行
DISPATCH_QUEUE_PRIORITY_DEFAULT 默認(rèn)優(yōu)先級(jí),在low之前轿偎,在high之后
DISPATCH_QUEUE_PRIORITY_LOW 在high和default后執(zhí)行
DISPATCH_QUEUE_PRIORITY_BACKGROUND:提交到這個(gè)隊(duì)列的任務(wù)會(huì)在high優(yōu)先級(jí)的任務(wù)和已經(jīng)提交到background隊(duì)列的執(zhí)行完后執(zhí)行典鸡。官方文檔:(the queue is scheduled for execution after all high priority queues have been scheduled and the system runs items on a thread whose priority is set for background status.)

二、dispatch_async與dispatch_sync

  • dispatch_sync
    提交到隊(duì)列中同步執(zhí)行
  • dispatch_async
    提交到隊(duì)列中異步執(zhí)行坏晦,立即返回
  • dispatch_barrier_sync
  • dispatch_barrier_async
    在隊(duì)列中萝玷,柵欄塊必須單獨(dú)執(zhí)行,不能與其它塊并行昆婿。這只對(duì)隊(duì)列有意義球碉,因?yàn)榇嘘?duì)列中的塊總是按順序逐個(gè)來執(zhí)行的。并發(fā)隊(duì)列中如果發(fā)現(xiàn)接下來要處理的塊是個(gè)柵欄塊(barrier block),那么就一直等到當(dāng)前所有并發(fā)塊都執(zhí)行完畢挖诸,才會(huì)單獨(dú)執(zhí)行這個(gè)柵欄塊汁尺。

這是Effective Objective-C 2.0 這本書 中對(duì)dispatch_barrier_async的說明法精,書中有一段示例代碼多律,大概是這樣的:

 - (instancetype)init
 {
        self = [super init];
        if (!self) {
              return nil;
        }
        _concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
       return self;
  }

 - (NSString *)name
 {
         __block NSString *name;
        dispatch_sync(_concurrentQueue, ^{
             name = _name;
        });
        return name;
 }

 - (void)setName:(NSString *)name
 {
       dispatch_barrier_async(_concurrentQueue, ^{
             _name = name;
      });
  }

問題來了,以上代碼能實(shí)現(xiàn)對(duì)name屬性的讀寫同步嗎搂蜓?
按道理狼荞,是可以的。但事實(shí)并不可以帮碰,因?yàn)樵谶@里蘋果給我們挖了一個(gè)坑相味。。殉挽。
原因就是 在這里 我們使用的是全局并發(fā)隊(duì)列丰涉。。
都是 并發(fā)隊(duì)列 憑啥就不一樣呢斯碌?一死?

就是說,柵欄塊應(yīng)該在自己創(chuàng)建的并行隊(duì)列里執(zhí)行傻唾,如果是在串行隊(duì)列或是全局并行隊(duì)列中執(zhí)行投慈,那么就起不到柵欄的作用,和dispatch_async 函數(shù)效果一樣了冠骄。

所以上面代碼只要把_concurrentQueue 改成自己創(chuàng)建的

 _concurrentQueue = dispatch_queue_create("com.people.test", DISPATCH_QUEUE_CONCURRENT);

就可以實(shí)現(xiàn) 讀寫的同步了伪煤。

隔離隊(duì)列

再來理解一個(gè)隔離隊(duì)列的概念,也是跟dispatch_barrier_sync和dispatch_barrier_async有關(guān)凛辣。

例如操作系統(tǒng)中的經(jīng)典的讀者-寫者問題抱既,簡而言之,我們可以在同一時(shí)刻有多個(gè)讀者扁誓,但同一時(shí)刻只能有一個(gè)線程可以寫入防泵。解決方法就是利用GCD的四種 APIs

  • dispatch_sync
  • dispatch_async
  • dispatch_barrier_sync
  • dispatch_barrier_async

我們的想法是讀操作可以支持同步和異步阳堕,而寫操作也能支持異步寫入,并且必須確保是寫入的是同一個(gè)引用择克。GCD 的 barrier 集合 APIs 提供了解決方案:他們將會(huì)一直等到隊(duì)列中的任務(wù)清空恬总,才會(huì)繼續(xù)執(zhí)行 block。使用 barrier APIs 可以用來限制我們對(duì)字典對(duì)象的寫入肚邢,并且確保我們不會(huì)在同一時(shí)刻進(jìn)行多個(gè)寫操作壹堰,以及正在寫操作時(shí)同時(shí)進(jìn)行讀操作÷夂看一段代碼:

 class IdentityMap<T: Identifiable> {  
var dictionary = Dictionary<String, T>()
let accessQueue = dispatch_queue_create("com.khanlou.isolation.queue", DISPATCH_QUEUE_CONCURRENT)

func object(withID ID: String) -> T? {
    var result: T? = nil
    dispatch_sync(accessQueue, {
        result = dictionary[ID] as T?
    })
    return result
}

func addObject(object: T) {
    dispatch_barrier_async(accessQueue, {
        dictionary[object.ID] = object
    })
}
}

dispatch_sync 將會(huì)分發(fā) block 到我們的隔離隊(duì)列上然后等待其執(zhí)行完畢贱纠。通過這種方式,我們就實(shí)現(xiàn)了同步讀操作(如果我們搞成異步讀取响蕴,getter 方法就需要一個(gè) completion block)谆焊。因?yàn)?accessQueue 是并發(fā)隊(duì)列,這些同步讀取操作可以并發(fā)執(zhí)行浦夷,也就是允許同時(shí)讀廷臼。

dispatch_barrier_async 將分發(fā) block 到隔離隊(duì)列上携茂,async 異步部分意味著會(huì)立即返回,并不會(huì)等待 block 執(zhí)行完畢。這對(duì)性能是有好處的牙咏,但是在一個(gè)寫操作后立即執(zhí)行一個(gè)讀操作會(huì)導(dǎo)致讀到一個(gè)半成品的數(shù)據(jù)(因?yàn)榭赡軐懖僮鬟€未完成就開始讀了)掩驱。

dispatch_barrier_async 中的 barrier 部分意味著:只要 barrier block 進(jìn)入隊(duì)列撒轮,并不會(huì)立即執(zhí)行巩掺,而是會(huì)等待該隊(duì)列其他 block 執(zhí)行完畢后再執(zhí)行。所以在這點(diǎn)上就保證了我們的 barrier block 每次都只有它自己在執(zhí)行续膳。而所有在他之后提交的 block 也會(huì)一直等待這個(gè) barrier block 執(zhí)行完再執(zhí)行改艇。

傳入 dispatch_barrier_async() 函數(shù)的 queue,必須是用 dispatch_queue_create 創(chuàng)建的并發(fā) queue坟岔。如果是串行 queue 或者是 global concurrent queues谒兄,這個(gè)函數(shù)就會(huì)變成 dispatch_async() 了

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市炮车,隨后出現(xiàn)的幾起案子舵变,更是在濱河造成了極大的恐慌,老刑警劉巖瘦穆,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纪隙,死亡現(xiàn)場離奇詭異,居然都是意外死亡扛或,警方通過查閱死者的電腦和手機(jī)绵咱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來熙兔,“玉大人悲伶,你說我怎么就攤上這事艾恼。” “怎么了麸锉?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵钠绍,是天一觀的道長。 經(jīng)常有香客問我花沉,道長柳爽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任碱屁,我火速辦了婚禮磷脯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘娩脾。我一直安慰自己赵誓,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布柿赊。 她就那樣靜靜地躺著俩功,像睡著了一般。 火紅的嫁衣襯著肌膚如雪闹瞧。 梳的紋絲不亂的頭發(fā)上绑雄,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天展辞,我揣著相機(jī)與錄音奥邮,去河邊找鬼。 笑死罗珍,一個(gè)胖子當(dāng)著我的面吹牛洽腺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播覆旱,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼蘸朋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了扣唱?” 一聲冷哼從身側(cè)響起藕坯,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎噪沙,沒想到半個(gè)月后炼彪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡正歼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年辐马,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片局义。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡喜爷,死狀恐怖冗疮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情檩帐,我是刑警寧澤术幔,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站湃密,受9級(jí)特大地震影響特愿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜勾缭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一揍障、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧俩由,春花似錦毒嫡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至碘梢,卻和暖如春咬摇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背煞躬。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來泰國打工肛鹏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人恩沛。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓在扰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親雷客。 傳聞我的和親對(duì)象是個(gè)殘疾皇子芒珠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 簡介 GCD(Grand Central Dispatch)是在macOS10.6提出來的,后來在iOS4.0被引...
    sunmumu1222閱讀 850評(píng)論 0 2
  • 本篇博客共分以下幾個(gè)模塊來介紹GCD的相關(guān)內(nèi)容: 多線程相關(guān)概念 多線程編程技術(shù)的優(yōu)缺點(diǎn)比較搅裙? GCD中的三種隊(duì)列...
    dullgrass閱讀 37,834評(píng)論 30 236
  • iOS中GCD的使用小結(jié) 作者dullgrass 2015.11.20 09:41*字?jǐn)?shù) 4996閱讀 20199...
    DanDanC閱讀 814評(píng)論 0 0
  • 我們知道在iOS開發(fā)中皱卓,一共有四種多線程技術(shù):pthread,NSThread部逮,GCD娜汁,NSOperation: ...
    請叫我周小帥閱讀 1,484評(píng)論 0 1
  • 最近常常晚上一點(diǎn)左右被痛苦的咳嗽憋醒。剛開始特別難受甥啄,坐起來后做一些自己白天沒來得及做的不正經(jīng)的或者想做的事情存炮,半...
    學(xué)會(huì)取悅自己閱讀 227評(píng)論 0 0