GCD中的dispatch_semaphore的使用(信號(hào)量)

理解這個(gè)概念之前,先拋出一個(gè)問(wèn)題

問(wèn)題描述:

假設(shè)現(xiàn)在系統(tǒng)有兩個(gè)空閑資源可以被利用,但同一時(shí)間卻有三個(gè)線程要進(jìn)行訪問(wèn),這種情況下,該如何處理呢?
或者
我們要下載很多圖片,并發(fā)異步進(jìn)行,每個(gè)下載都會(huì)開辟一個(gè)新線程,可是我們又擔(dān)心太多線程肯定CPU吃不消,那么我們這里也可以用信號(hào)量控制一下最大開辟線程數(shù)。

定義:

1、信號(hào)量:就是一種可用來(lái)控制訪問(wèn)資源的數(shù)量的標(biāo)識(shí),設(shè)定了一個(gè)信號(hào)量,在線程訪問(wèn)之前,加上信號(hào)量的處理,則可告知系統(tǒng)按照我們指定的信號(hào)量數(shù)量來(lái)執(zhí)行多個(gè)線程。
其實(shí),這有點(diǎn)類似鎖機(jī)制了,只不過(guò)信號(hào)量都是系統(tǒng)幫助我們處理了,我們只需要在執(zhí)行線程之前,設(shè)定一個(gè)信號(hào)量值,并且在使用時(shí),加上信號(hào)量處理方法就行了。

2、信號(hào)量主要有3個(gè)函數(shù),分別是:

//創(chuàng)建信號(hào)量,參數(shù):信號(hào)量的初值,如果小于0則會(huì)返回NULL
dispatch_semaphore_create(信號(hào)量值)
 
//等待降低信號(hào)量
dispatch_semaphore_wait(信號(hào)量,等待時(shí)間)
 
//提高信號(hào)量
dispatch_semaphore_signal(信號(hào)量)

注意,正常的使用順序是先降低然后再提高,這兩個(gè)函數(shù)通常成對(duì)使用。

3、那么就開頭提的問(wèn)題,我們用代碼來(lái)解決

-(void)dispatchSignal{
    //crate的value表示,最多幾個(gè)資源可訪問(wèn)
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);   
    dispatch_queue_t quene = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
     
    //任務(wù)1
    dispatch_async(quene, ^{
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        NSLog(@"run task 1");
        sleep(1);
        NSLog(@"complete task 1");
        dispatch_semaphore_signal(semaphore);       
    });
    //任務(wù)2
    dispatch_async(quene, ^{
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        NSLog(@"run task 2");
        sleep(1);
        NSLog(@"complete task 2");
        dispatch_semaphore_signal(semaphore);       
    });
    //任務(wù)3
    dispatch_async(quene, ^{
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        NSLog(@"run task 3");
        sleep(1);
        NSLog(@"complete task 3");
        dispatch_semaphore_signal(semaphore);       
    });   
}

控制臺(tái)輸出:

2018-04-19 15:24:09.260057+0800 Barrier[71701:2876327] run task 2
2018-04-19 15:24:09.260057+0800 Barrier[71701:2876329] run task 1
2018-04-19 15:24:10.265626+0800 Barrier[71701:2876329] complete task 1
2018-04-19 15:24:10.265618+0800 Barrier[71701:2876327] complete task 2
2018-04-19 15:24:10.266074+0800 Barrier[71701:2876326] run task 3
2018-04-19 15:24:11.270587+0800 Barrier[71701:2876326] complete task 3

總結(jié):由于設(shè)定的信號(hào)值為2,先執(zhí)行兩個(gè)線程,等執(zhí)行完一個(gè),才會(huì)繼續(xù)執(zhí)行下一個(gè),保證同一時(shí)間執(zhí)行的線程數(shù)不超過(guò)2。

這里我們擴(kuò)展一下,假設(shè)我們?cè)O(shè)定信號(hào)值=1

dispatch_semaphore_create(1)

那么結(jié)果就是:

2018-04-19 15:25:48.402966+0800 Barrier[71755:2879923] run task 1
2018-04-19 15:25:49.408142+0800 Barrier[71755:2879923] complete task 1
2018-04-19 15:25:49.408424+0800 Barrier[71755:2879910] run task 2
2018-04-19 15:25:50.413553+0800 Barrier[71755:2879910] complete task 2
2018-04-19 15:25:50.413772+0800 Barrier[71755:2879908] run task 3
2018-04-19 15:25:51.418006+0800 Barrier[71755:2879908] complete task 3

如果設(shè)定信號(hào)值=3

dispatch_semaphore_create(3)

那么結(jié)果就是:

2018-04-19 15:26:53.338567+0800 Barrier[71792:2883332] run task 3
2018-04-19 15:26:53.338567+0800 Barrier[71792:2883330] run task 1
2018-04-19 15:26:53.338567+0800 Barrier[71792:2883333] run task 2
2018-04-19 15:26:54.343147+0800 Barrier[71792:2883333] complete task 2
2018-04-19 15:26:54.343147+0800 Barrier[71792:2883330] complete task 1
2018-04-19 15:26:54.343192+0800 Barrier[71792:2883332] complete task 3





猜猜這里會(huì)如何輸出?

- (void)semaphore {
    dispatch_group_t group = dispatch_group_create();
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);
//    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_queue_t queue = dispatch_queue_create("QueueName", DISPATCH_QUEUE_CONCURRENT);
    for (int i=0; i<100; i++) {
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        dispatch_group_async(group, queue, ^{
            NSLog(@"----%d", i);
            sleep(2);
            dispatch_semaphore_signal(semaphore);
        });
    }
    NSLog(@"hello");
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    NSLog(@"world");
}

通俗來(lái)說(shuō):
dispatch_semaphore_create(10)這會(huì)創(chuàng)建10個(gè)信號(hào)量。
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);每執(zhí)行一次這個(gè)方法就會(huì)讓信號(hào)量減一,當(dāng)信號(hào)量小于零的時(shí)候,會(huì)處于一直等待的狀態(tài)。
dispatch_semaphore_signal(semaphore);每執(zhí)行一次這個(gè)方法,就會(huì)讓信號(hào)量加一,此時(shí)就表示有一個(gè)線程完成了,可以再重新開一個(gè)線程了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容