一、定義
1、信號量:就是一種可用來控制訪問資源的數(shù)量的標識,設(shè)定了一個信號量,在線程訪問之前,加上信號量的處理,則可告知系統(tǒng)按照我們指定的信號量數(shù)量來執(zhí)行多個線程。
其實,這有點類似鎖機制了,只不過信號量都是系統(tǒng)幫助我們處理了,我們只需要在執(zhí)行線程之前,設(shè)定一個信號量值,并且在使用時,加上信號量處理方法就行了。2、簡單來講 信號量為0則阻塞線程,大于0則不會阻塞。則我們通過改變信號量的值,來控制是否阻塞線程,從而達到線程同步
-
3、信號量主要有3個函數(shù),分別是:
//創(chuàng)建信號量,參數(shù):信號量的初值,如果小于0則會返回NULL dispatch_semaphore_create(信號量值) //等待降低信號量 dispatch_semaphore_wait(信號量,等待時間) //提高信號量 dispatch_semaphore_signal(信號量) -
4、關(guān)于信號量,一般可以用停車來比喻
停車場剩余4個車位,那么即使同時來了四輛車也能停的下。如果此時來了五輛車,那么就有一輛需要等待。信號量的值就相當于剩余車位的數(shù)目。
dispatch_semaphore_wait函數(shù)就相當于來了一輛車,dispatch_semaphore_signal就相當于走了一輛車。停車位的剩余數(shù)目在初始化的時候就已經(jīng)指明了(dispatch_semaphore_create(long value)),調(diào)用一次dispatch_semaphore_signal,剩余的車位就增加一個;調(diào)用一次dispatch_semaphore_wait剩余車位就減少一個;當剩余車位為0時,再來車(即調(diào)用dispatch_semaphore_wait)就只能等待。有可能同時有幾輛車等待一個停車位。有些車主沒有耐心,給自己設(shè)定了一段等待時間,這段時間內(nèi)等不到停車位就走了,如果等到了就開進去停車。而有些車主就像把車停在這,所以就一直等下去。
二、使用場景1
假設(shè)現(xiàn)在系統(tǒng)有兩個空閑資源可以被利用,但同一時間卻有三個線程要進行訪問,這種情況下,該如何處理呢?
//crate的value表示,最多幾個資源可訪問
dispatch_semaphore_t samphore = dispatch_semaphore_create(2);
dispatch_queue_t quene = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//dispatch_queue_t quene = dispatch_queue_create("com.anji.jiajia", DISPATCH_QUEUE_CONCURRENT);
//任務(wù)1
dispatch_async(quene, ^{
dispatch_semaphore_wait(samphore, DISPATCH_TIME_FOREVER);
NSLog(@"run task 1");
sleep(1);
NSLog(@"completed task 1");
dispatch_semaphore_signal(samphore);
});
//任務(wù)2
dispatch_async(quene, ^{
dispatch_semaphore_wait(samphore, DISPATCH_TIME_FOREVER);
NSLog(@"run task 2");
sleep(1);
NSLog(@"completed task 2");
dispatch_semaphore_signal(samphore);
});
//任務(wù)3
dispatch_async(quene, ^{
dispatch_semaphore_wait(samphore, DISPATCH_TIME_FOREVER);
NSLog(@"run task 3");
sleep(1);
NSLog(@"completed task 3");
dispatch_semaphore_signal(samphore);
});
運行結(jié)果:
2017-12-20 13:35:34.308282+0800 OCDemo[61949:15613320] run task 1
2017-12-20 13:35:34.308291+0800 OCDemo[61949:15613317] run task 2
2017-12-20 13:35:35.310784+0800 OCDemo[61949:15613320] completed task 1
2017-12-20 13:35:35.310784+0800 OCDemo[61949:15613317] completed task 2
2017-12-20 13:35:35.311016+0800 OCDemo[61949:15613319] run task 3
2017-12-20 13:35:36.313924+0800 OCDemo[61949:15613319] completed task 3
三、使用場景2
我們要下載很多圖片,并發(fā)異步進行,每個下載都會開辟一個新線程,可是我們又擔心太多線程肯定cpu吃不消,那么我們這里也可以用信號量控制一下最大開辟線程數(shù)。
//crate的value表示,最多幾個資源可訪問
dispatch_semaphore_t samphore = dispatch_semaphore_create(5);
dispatch_queue_t quene = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < 15; i++) {
dispatch_async(quene, ^{
dispatch_semaphore_wait(samphore, DISPATCH_TIME_FOREVER);
NSLog(@"run task %d", i);
[self downloadImge:^(BOOL isSuccess, NSString *errorMsg) {
NSLog(@"BLock completed %d", i);
dispatch_semaphore_signal(samphore);
}];
});
}
由于是異步執(zhí)行的,所以每次循環(huán)Block就會執(zhí)行dispatch_semaphore_wait,從而semaphore-1.當循環(huán)5次后semaphore==0,則會阻塞線程,直到執(zhí)行了Block的dispatch_semaphore_signal 才會繼續(xù)執(zhí)行。
四、使用場景3
在開發(fā)中我們需要處理下載多張照片等待所有網(wǎng)絡(luò)回調(diào)完之后才執(zhí)行后面的操作?;蛘叩却鄠€網(wǎng)絡(luò)請求,所有請求成功后數(shù)據(jù)融合處理。
//crate的value表示,最多幾個資源可訪問
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t quene = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < 5; i++) {
dispatch_group_async(group, quene, ^{
dispatch_semaphore_t samphore = dispatch_semaphore_create(0);
[self downloadImge:^(BOOL isSuccess, NSString *errorMsg) {
NSLog(@"task %d completed ", i);
dispatch_semaphore_signal(samphore);
}];
dispatch_semaphore_wait(samphore, DISPATCH_TIME_FOREVER);
});
}
dispatch_group_notify(group, quene, ^{
NSLog(@"All task completed ====");
});
運行結(jié)果:
2017-12-20 14:22:03.162137+0800 OCDemo[64177:15790354] task 0 completed
2017-12-20 14:22:03.162138+0800 OCDemo[64177:15790351] task 3 completed
2017-12-20 14:22:04.165827+0800 OCDemo[64177:15790352] task 2 completed
2017-12-20 14:22:05.167003+0800 OCDemo[64177:15790368] task 4 completed
2017-12-20 14:22:05.166964+0800 OCDemo[64177:15790353] task 1 completed
2017-12-20 14:22:05.167153+0800 OCDemo[64177:15790368] All task completed ====