119,iOS GCD之dispatch_semaphore學(xué)習(xí)

首先,我理解的dispatch_semaphore有兩個(gè)主要應(yīng)用 :

1. 保持線程同步
2. 為線程加鎖

先看下相關(guān)的3個(gè)方法:

  • dispatch_semaphore_t dispatch_semaphore_create(long value):方法接收一個(gè)long類型的參數(shù), 返回一個(gè)dispatch_semaphore_t類型的信號(hào)量住册,值為

這個(gè)參數(shù)一定要是大于等于0的
dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout)```:接收一個(gè)信號(hào)和時(shí)間值,若信號(hào)的信號(hào)量為0且预,則會(huì)阻塞當(dāng)前線程槽袄,直到信號(hào)量大于0或者經(jīng)過(guò)輸入的時(shí)間值;若信號(hào)量大于0锋谐,則會(huì)使信號(hào)量減1并返回遍尺,程序繼續(xù)住下執(zhí)行

  • long dispatch_semaphore_signal(dispatch_semaphore_t dsema):使信號(hào)量加1并返回

介紹完了相關(guān)方法,下面開(kāi)始介紹兩種應(yīng)用

保持線程同步

先看代碼

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block int j = 0;
dispatch_async(queue, ^{
       j = 100;
      dispatch_semaphore_signal(semaphore);
});

dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"finish j = %zd", j);

結(jié)果輸出 j = 100怀估;
如果注掉dispatch_semaphore_wait這一行狮鸭,則 j = 0;
注釋: 由于是將block異步添加到一個(gè)并行隊(duì)列里面多搀,所以程序在主線程躍過(guò)block直接到dispatch_semaphore_wait這一行歧蕉,因?yàn)?code>semaphore信號(hào)量為0,時(shí)間值為DISPATCH_TIME_FOREVER康铭,所以當(dāng)前線程會(huì)一直阻塞惯退,直到block在子線程執(zhí)行到dispatch_semaphore_signal,使信號(hào)量+1从藤,此時(shí)semaphore信號(hào)量為1了催跪,所以程序繼續(xù)往下執(zhí)行。這就保證了線程間同步了夷野。

為線程加鎖
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);

for (int i = 0; i <100; i++) {
dispatch_async(queue, ^{
 // 相當(dāng)于加鎖
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"i = %zd semaphore = %@", i, semaphore);
// 相當(dāng)于解鎖
dispatch_semaphore_signal(semaphore);
});
}

注釋:當(dāng)線程1執(zhí)行到dispatch_semaphore_wait這一行時(shí)懊蒸,semaphore的信號(hào)量為1,所以使信號(hào)量-1變?yōu)?悯搔,并且線程1繼續(xù)往下執(zhí)行骑丸;如果當(dāng)在線程1NSLog這一行代碼還沒(méi)執(zhí)行完的時(shí)候,又有線程2來(lái)訪問(wèn)妒貌,執(zhí)行dispatch_semaphore_wait時(shí)由于此時(shí)信號(hào)量為0通危,且時(shí)間為DISPATCH_TIME_FOREVER,所以會(huì)一直阻塞線程2(此時(shí)線程2處于等待狀態(tài)),直到線程1執(zhí)行完NSLog并執(zhí)行完dispatch_semaphore_signal使信號(hào)量為1后灌曙,線程2才能解除阻塞繼續(xù)住下執(zhí)行菊碟。以上可以保證同時(shí)只有一個(gè)線程執(zhí)行NSLog這一行代碼。

簡(jiǎn)單來(lái)講 信號(hào)量為0則阻塞線程在刺,大于0則不會(huì)阻塞逆害。則我們通過(guò)改變信號(hào)量的值,來(lái)控制是否阻塞線程蚣驼,從而達(dá)到線程同步.

下面我們逐一介紹三個(gè)函數(shù):

(1)dispatch_semaphore_create的聲明為:

dispatch_semaphore_t dispatch_semaphore_create(long value);

傳入的參數(shù)為long忍燥,輸出一個(gè)dispatch_semaphore_t類型且值為value的信號(hào)量。

值得注意的是隙姿,這里的傳入的參數(shù)value必須大于或等于0,否則dispatch_semaphore_create會(huì)返回NULL厂捞。

(關(guān)于信號(hào)量输玷,我就不在這里累述了队丝,網(wǎng)上很多介紹這個(gè)的。我們這里主要講一下dispatch_semaphore這三個(gè)函數(shù)的用法)欲鹏。

(2)dispatch_semaphore_signal的聲明為:

long dispatch_semaphore_signal(dispatch_semaphore_t dsema)

這個(gè)函數(shù)會(huì)使傳入的信號(hào)量dsema的值加1机久;(至于返回值,待會(huì)兒再講)

(3) dispatch_semaphore_wait的聲明為:

long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout)赔嚎;

這個(gè)函數(shù)會(huì)使傳入的信號(hào)量dsema的值減1膘盖;

這個(gè)函數(shù)的作用是這樣的,如果dsema信號(hào)量的值大于0尤误,該函數(shù)所處線程就繼續(xù)執(zhí)行下面的語(yǔ)句侠畔,并且將信號(hào)量的值減1

如果desema的值為0损晤,那么這個(gè)函數(shù)就阻塞當(dāng)前線程等待timeout(注意timeout的類型為dispatch_time_t软棺,

不能直接傳入整形或float型數(shù)),如果等待的期間desema的值被dispatch_semaphore_signal函數(shù)加1了尤勋,

且該函數(shù)(即dispatch_semaphore_wait)所處線程獲得了信號(hào)量喘落,那么就繼續(xù)向下執(zhí)行并將信號(hào)量減1

如果等待期間沒(méi)有獲取到信號(hào)量或者信號(hào)量的值一直為0最冰,那么等到timeout時(shí)瘦棋,其所處線程自動(dòng)執(zhí)行其后語(yǔ)句。

(4)dispatch_semaphore_signal的返回值為long類型暖哨,當(dāng)返回值為0時(shí)表示當(dāng)前并沒(méi)有線程等待其處理的信號(hào)量赌朋,其處理

的信號(hào)量的值加1即可。當(dāng)返回值不為0時(shí)鹿蜀,表示其當(dāng)前有(一個(gè)或多個(gè))線程等待其處理的信號(hào)量箕慧,并且該函數(shù)喚醒了一

個(gè)等待的線程(當(dāng)線程有優(yōu)先級(jí)時(shí),喚醒優(yōu)先級(jí)最高的線程茴恰;否則隨機(jī)喚醒)颠焦。

dispatch_semaphore_wait的返回值也為long型。當(dāng)其返回0時(shí)表示在timeout之前往枣,該函數(shù)所處的線程被成功喚醒伐庭。

當(dāng)其返回不為0時(shí),表示timeout發(fā)生分冈。

隊(duì)列加鎖
// 創(chuàng)建隊(duì)列組
    dispatch_group_t group = dispatch_group_create();   
// 創(chuàng)建信號(hào)量圾另,并且設(shè)置值為10
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);   
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);   
    for (int i = 0; i < 100; i++)   
    {   // 由于是異步執(zhí)行的,所以每次循環(huán)Block里面的dispatch_semaphore_signal根本還沒(méi)有執(zhí)行就會(huì)執(zhí)行dispatch_semaphore_wait雕沉,從而semaphore-1.當(dāng)循環(huán)10此后集乔,semaphore等于0,則會(huì)阻塞線程坡椒,直到執(zhí)行了Block的dispatch_semaphore_signal 才會(huì)繼續(xù)執(zhí)行
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);   
        dispatch_group_async(group, queue, ^{   
            NSLog(@"%i",i);   
            sleep(2);   
// 每次發(fā)送信號(hào)則semaphore會(huì)+1扰路,
            dispatch_semaphore_signal(semaphore);   
        });   
    }   
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末尤溜,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子汗唱,更是在濱河造成了極大的恐慌宫莱,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,331評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哩罪,死亡現(xiàn)場(chǎng)離奇詭異授霸,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)际插,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,372評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門碘耳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人腹鹉,你說(shuō)我怎么就攤上這事藏畅〉欠颍” “怎么了靖避?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,755評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)椅野。 經(jīng)常有香客問(wèn)我力奋,道長(zhǎng)榜旦,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,528評(píng)論 1 296
  • 正文 為了忘掉前任景殷,我火速辦了婚禮溅呢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘猿挚。我一直安慰自己咐旧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,526評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布绩蜻。 她就那樣靜靜地躺著铣墨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪办绝。 梳的紋絲不亂的頭發(fā)上伊约,一...
    開(kāi)封第一講書(shū)人閱讀 52,166評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音孕蝉,去河邊找鬼屡律。 笑死,一個(gè)胖子當(dāng)著我的面吹牛降淮,可吹牛的內(nèi)容都是我干的超埋。 我是一名探鬼主播,決...
    沈念sama閱讀 40,768評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼霍殴!你這毒婦竟也來(lái)了窍蓝?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,664評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤繁成,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后淑玫,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體巾腕,經(jīng)...
    沈念sama閱讀 46,205評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,290評(píng)論 3 340
  • 正文 我和宋清朗相戀三年絮蒿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了尊搬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,435評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡土涝,死狀恐怖佛寿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情但壮,我是刑警寧澤冀泻,帶...
    沈念sama閱讀 36,126評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站蜡饵,受9級(jí)特大地震影響弹渔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜溯祸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,804評(píng)論 3 333
  • 文/蒙蒙 一肢专、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧焦辅,春花似錦博杖、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,276評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至仆抵,卻和暖如春跟继,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背镣丑。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工舔糖, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人莺匠。 一個(gè)月前我還...
    沈念sama閱讀 48,818評(píng)論 3 376
  • 正文 我出身青樓金吗,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子摇庙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,442評(píng)論 2 359