信號(hào)量(Semaphore)柜思,有時(shí)被稱(chēng)為信號(hào)燈姑隅,是在多線程環(huán)境下使用的一種設(shè)施莱坎,是可以用來(lái)保證兩個(gè)或多個(gè)關(guān)鍵代碼段不被并發(fā)調(diào)用蛛蒙。在進(jìn)入一個(gè)關(guān)鍵代碼段之前糙箍,線程必須獲取一個(gè)信號(hào)量;一旦該關(guān)鍵代碼段完成了宇驾,那么該線程必須釋放信號(hào)量倍靡。其它想進(jìn)入該關(guān)鍵代碼段的線程必須等待直到第一個(gè)線程釋放信號(hào)量。為了完成這個(gè)過(guò)程课舍,需要?jiǎng)?chuàng)建一個(gè)信號(hào)量VI,然后將Acquire Semaphore VI以及Release Semaphore VI分別放置在每個(gè)關(guān)鍵代碼段的首末端他挎。確認(rèn)這些信號(hào)量VI引用的是初始創(chuàng)建的信號(hào)
以一個(gè)停車(chē)場(chǎng)的運(yùn)作為例筝尾。簡(jiǎn)單起見(jiàn),假設(shè)停車(chē)場(chǎng)只有三個(gè)車(chē)位办桨,一開(kāi)始三個(gè)車(chē)位都是空的筹淫。這時(shí)如果同時(shí)來(lái)了五輛車(chē),看門(mén)人允許其中三輛直接進(jìn)入呢撞,然后放下車(chē)攔损姜,剩下的車(chē)則必須在入口等待饰剥,此后來(lái)的車(chē)也都不得不在入口處等待。這時(shí)摧阅,有一輛車(chē)離開(kāi)停車(chē)場(chǎng)汰蓉,看門(mén)人得知后,打開(kāi)車(chē)攔棒卷,放入外面的一輛進(jìn)去顾孽,如果又離開(kāi)兩輛,則又可以放入兩輛比规,如此往復(fù)若厚。
在這個(gè)停車(chē)場(chǎng)系統(tǒng)中,車(chē)位是公共資源蜒什,每輛車(chē)好比一個(gè)線程测秸,看門(mén)人起的就是信號(hào)量的作用。
抽象的來(lái)講灾常,信號(hào)量的特性如下:信號(hào)量是一個(gè)非負(fù)整數(shù)(車(chē)位數(shù))乞封,所有通過(guò)它的線程/進(jìn)程(車(chē)輛)都會(huì)將該整數(shù)減一(通過(guò)它當(dāng)然是為了使用資源),當(dāng)該整數(shù)值為零時(shí)岗憋,所有試圖通過(guò)它的線程都將處于等待狀態(tài)肃晚。在信號(hào)量上我們定義兩種操作: Wait(等待) 和 Release(釋放)。當(dāng)一個(gè)線程調(diào)用Wait操作時(shí)仔戈,它要么得到資源然后將信號(hào)量減一关串,要么一直等下去(指放入阻塞隊(duì)列),直到信號(hào)量大于等于一時(shí)监徘。Release(釋放)實(shí)際上是在信號(hào)量上執(zhí)行加操作晋修,對(duì)應(yīng)于車(chē)輛離開(kāi)停車(chē)場(chǎng),該操作之所以叫做“釋放”是因?yàn)獒尫帕擞尚盘?hào)量守護(hù)的資源凰盔。
以上是百度百科內(nèi)容方便理解信號(hào)量
對(duì)信號(hào)量有4種操作:
1. 初始化(initialize)墓卦,也叫做建立(create):
dispatch_semaphore_t dispatch_semaphore_create( long value);
2. 等信號(hào)(wait),也可叫做掛起(suspend):
線程等待信號(hào)量户敬,如果值大于0落剪,則獲得,值減一尿庐;如果值等于0忠怖,則線程進(jìn)入睡眠狀態(tài),只到信號(hào)量值大于0或者超時(shí)抄瑟。
long dispatch_semaphore_wait( dispatch_semaphore_t dsema, dispatch_time_t timeout);
如果返回的結(jié)果是0說(shuō)明線程線程被成功喚醒,非0說(shuō)明超時(shí);
3. 給信號(hào)(signal)或發(fā)信號(hào)(post):
執(zhí)行釋放信號(hào)量凡泣,則值加一;如果此時(shí)有正在等待的線程,則喚醒該線程鞋拟。
long dispatch_semaphore_signal( dispatch_semaphore_t dsema);
如果返回的是非零的數(shù)字則說(shuō)明有一個(gè)線程被喚醒,返回0則說(shuō)明沒(méi)有線程被喚醒(說(shuō)明沒(méi)有wait的線程)
4.清理(destroy):
dispatch_release(object) //在ARC中不需要此步驟
示例代碼
dispatch_group_t group = dispatch_group_create();
dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < 100; i++)
{
long l1 = dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"l1:%ld",l1);
NSLog(@"semaphore:%@",semaphore.accessibilityValue);
dispatch_group_async(group, queue, ^{
NSLog(@"%i",i);
sleep(2);
long l2 = dispatch_semaphore_signal(semaphore);
NSLog(@"l2:%ld",l2);
});
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);