在這周的程序開發(fā)中用到了GCD中的信號量和隊(duì)列組诗祸,由于對信號量不熟悉,特地來復(fù)習(xí)一下這方面的知識蹲诀。
概念
信號量是用于多線程同步的迂苛,跟鎖不一樣的是三热,信號量不一定是鎖定某一個(gè)資源,而是流程上的概念三幻,比如:有A,B兩個(gè)線程就漾,B線程要等A線程完成某一任務(wù)以后再進(jìn)行自己下面的步驟,這個(gè)任務(wù) 并不一定是鎖定某一資源念搬,還可以是進(jìn)行一些計(jì)算或者數(shù)據(jù)處理之類抑堡。而對于鎖來說,鎖住的資源無法被其余的線程訪問朗徊,從而阻塞線程而實(shí)現(xiàn)線程同步首妖。
函數(shù)介紹
gcd的信號量主要有3個(gè)函數(shù),分別為
dispatch_semaphore_create(M)
創(chuàng)建一個(gè)值為M的信號量
dispatch_semaphore_wait(信號量爷恳,等待時(shí)間)
如果該信號量的值大于0有缆,則使其信號量的值-1,否則舌仍,阻塞線程直到該信號量的值大于0或者達(dá)到等待時(shí)間妒貌。
dispatch_semaphore_signal(信號量)
釋放信號量,使得該信號量的值加1
使用場景
信號量的使用場景應(yīng)該很多铸豁,下面舉幾個(gè)案例
限制線程的最大并發(fā)數(shù)
dispatch_semaphore_t sema = dispatch_semaphore_create(M);
for (NSInteger i = 0;i<N;i++) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
// doing
dispatch_semaphore_signal(sema);
});
}
如上述代碼可知灌曙,總共異步執(zhí)行N個(gè)任務(wù),但是由于我們設(shè)置了值為M的信號量节芥,每一次執(zhí)行任務(wù)的時(shí)候都會(huì)導(dǎo)致信號量的減1在刺,而在任務(wù)結(jié)束后使信號量加1,當(dāng)信號量減到0的時(shí)候头镊,說明正在執(zhí)行的任務(wù)有M個(gè)蚣驼,這個(gè)時(shí)候其它任務(wù)就會(huì)阻塞,直到有任務(wù)被完成時(shí)相艇,這些任務(wù)才會(huì)執(zhí)行颖杏。
阻塞發(fā)請求的線程
有些時(shí)候,我們需要阻塞發(fā)送請求的線程坛芽,比如在多個(gè)請求回調(diào)后統(tǒng)一操作的需求留储,而這些請求之間并沒有順序關(guān)系,且這些接口都會(huì)另開線程進(jìn)行網(wǎng)絡(luò)請求的咙轩。一般地获讳,這種多線程完成后進(jìn)行統(tǒng)一操作的需求都會(huì)使用隊(duì)列組(dispatch_group_t)來完成,但是由于是異步請求活喊,沒等其異步回調(diào)之后丐膝,請求的線程就結(jié)束了,為此,就需要使用信號量來阻塞住發(fā)請求的線程帅矗。實(shí)現(xiàn)代碼如下:
dispatch_async(queue, 0), ^{
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[網(wǎng)絡(luò)請求:^{
//請求回調(diào)
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
});
這樣偎肃,請求的線程就可以等到回調(diào)結(jié)束后再結(jié)束了,再配合隊(duì)列組就能完成上述的需求浑此。這種技巧可用于以下場景:
- 多個(gè)請求結(jié)束后統(tǒng)一操作
- 多個(gè)請求順序執(zhí)行