信號量概述(引用百度百科):
以一個停車場的運作為例。簡單起見,假設停車場只有三個車位,一開始三個車位都是空的。這時如果同時來了五輛車,看 門人允許其中三輛直接進入,然后放下車攔,剩下的車則必須在入口等待,此后來的車也都不得不在入口處等待。這時,有一輛車離開停車場,看門人得知后,打開 車攔,放入外面的一輛進去,如果又離開兩輛,則又可以放入兩輛,如此往復。在這個停車場系統(tǒng)中,車位是公共資源,每輛車好比一個線程,看門人起的就是信號量的作用。
抽象的來講,信號量的特性如下:信號量是一個非負整數(shù)(車位數(shù)),所有通過它的線程/進程(車輛)都會將該整數(shù)減一(通過它當然是為了使用資源),當該整數(shù)值為零時,所有試圖通過它的線程都將處于等待狀態(tài)。在信號量上我們定義兩種操作: Wait(等待) 和 Release(釋放)。當一個線程調(diào)用Wait操作時,它要么得到資源然后將信號量減一,要么一直等下去(指放入阻塞隊列),直到信號量大于等于一時。Release(釋放)實際上是在信號量上執(zhí)行加操作,對應于車輛離開停車場,該操作之所以叫做“釋放”是因為釋放了由信號量守護的資源。
Demo解析
1
// 創(chuàng)建一個信號量,值為0
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
// 在一個操作結(jié)束后發(fā)信號,這會使得信號量+1
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
dispatch_semaphore_signal(sema);
});
// 一開始執(zhí)行到這里信號量為0,線程被阻塞,直到上述操作完成使信號量+1,線程解除阻塞
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
2
// 創(chuàng)建一個組
dispatch_group_t group = dispatch_group_create();
// 創(chuàng)建信號 信號量為10
dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);
// 取得默認的全局并發(fā)隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for(int i = 0; i < 100; i++) {
// 由于信號量為10 隊列里面最多會有10個人任務被執(zhí)行,每次通過它信號量都減一,為0時就會等待
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
// 任務加到組內(nèi)被監(jiān)聽
dispatch_group_async(group, queue, ^{
NSLog(@"%i",i);
sleep(2);
//執(zhí)行此行代碼 信號量+1 如果為0 即0+1=1 上面wait語句又會放入一條任務 1-1=0 然后又陷入等待
//即車滿的停車場有一輛車離開 保安得知這個消息(信號量不為0)又開閘放了一輛車進來 (wait語句 1-1=0) 此時車又滿了 又執(zhí)行等待(信號量為0 執(zhí)行到wait語句等待)
dispatch_semaphore_signal(semaphore);
});
}
// 等待組內(nèi)所有任務完成,否則阻塞
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(group); //MRC
dispatch_release(semaphore); //MRC