簡(jiǎn)介
先來(lái)看看這幾個(gè)主要函數(shù):
/*
功能:創(chuàng)建信號(hào)量
參數(shù):value:信號(hào)量的初值,如果小于0則會(huì)返回NULL
返回值:信號(hào)量或空(失?。?*/
dispatch_semaphore_t dispatch_semaphore_create(long value);
/*
功能:阻塞當(dāng)前線程等待降低信號(hào)量;
當(dāng)信號(hào)量>0時(shí),繼續(xù)往下執(zhí)行并讓信號(hào)量減1
當(dāng)信號(hào)量=0時(shí),那么會(huì)等待信號(hào)量為非零才會(huì)執(zhí)行下一步
或是時(shí)間結(jié)束,執(zhí)行下一步
參數(shù):dsema:信號(hào)量 timeout:限定時(shí)間
返回值:信號(hào)量強(qiáng)度
*/
long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);
/*
功能:執(zhí)行結(jié)束,不需要占用資源,提高信號(hào)量+1
參數(shù):dsema:信號(hào)量
返回值:信號(hào)量強(qiáng)度
*/
long dispatch_semaphore_signal(dispatch_semaphore_t dsema);
可以理解為馬路上的車道,
當(dāng)信號(hào)量為1的時(shí)候就是1個(gè)車道,
當(dāng)信號(hào)量為2的時(shí)候就是2個(gè)車道允許兩輛車同時(shí)通過(guò)(兩個(gè)線程同時(shí)執(zhí)行)
信號(hào)量為1的時(shí)候可以控制線程執(zhí)行順序
某種意義上和 NSOperationQueue比較相似
信號(hào)量就是maxConcurrentOperationCount
示例1: 信號(hào)量1時(shí),控制線程執(zhí)行順序
//value 有幾個(gè)車道
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_queue_t quene = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//任務(wù)1
dispatch_async(quene, ^{
// NSLog(@"車1 發(fā)動(dòng)");
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"車1 開(kāi)始通過(guò)");
sleep(2);
NSLog(@"車1 已通過(guò)");
dispatch_semaphore_signal(semaphore);
});
//任務(wù)2
dispatch_async(quene, ^{
// NSLog(@"車2 發(fā)動(dòng)");
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"車2 開(kāi)始通過(guò)");
sleep(3);
NSLog(@"車2 已通過(guò)");
dispatch_semaphore_signal(semaphore);
});
//任務(wù)3
dispatch_async(quene, ^{
// NSLog(@"車3 發(fā)動(dòng)");
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"車3 開(kāi)始通過(guò)");
sleep(1);
NSLog(@"車3 已通過(guò)");
dispatch_semaphore_signal(semaphore);
});
輸出結(jié)果
2018-01-03 12:01:17.239713+0800 GCD_Demo[1068:198835] 車1 開(kāi)始通過(guò)
2018-01-03 12:01:19.242800+0800 GCD_Demo[1068:198835] 車1 已通過(guò)
2018-01-03 12:01:19.243025+0800 GCD_Demo[1068:199498] 車2 開(kāi)始通過(guò)
2018-01-03 12:01:22.248172+0800 GCD_Demo[1068:199498] 車2 已通過(guò)
2018-01-03 12:01:22.248436+0800 GCD_Demo[1068:199521] 車3 開(kāi)始通過(guò)
2018-01-03 12:01:23.253654+0800 GCD_Demo[1068:199521] 車3 已通過(guò)
這個(gè)案例中有個(gè)問(wèn)題
這個(gè)案例的前提條件是dispatch_semaphore_wait能按照順序執(zhí)行,但是三個(gè)任務(wù)都處于不同的線程,不能完全保證按照順序執(zhí)行;
當(dāng)然在正常情況下是沒(méi)問(wèn)題的,但是如果在dispatch_semaphore_wait之前加入NSLog(NSLog不僅僅只是打印信息,還記錄到log中應(yīng)該屬于耗時(shí)操作)
在案例中就是 NSLog(@"車1 發(fā)動(dòng)"); 注釋的相關(guān)代碼,輸出結(jié)果很不穩(wěn)定
2018-01-03 13:39:07.971221+0800 GCD_Demo[1280:300474] 車1 發(fā)動(dòng)
2018-01-03 13:39:07.971221+0800 GCD_Demo[1280:301289] 車2 發(fā)動(dòng)
2018-01-03 13:39:07.971241+0800 GCD_Demo[1280:301301] 車3 發(fā)動(dòng)
2018-01-03 13:39:07.971365+0800 GCD_Demo[1280:301289] 車2 開(kāi)始通過(guò)
2018-01-03 13:39:10.973622+0800 GCD_Demo[1280:301289] 車2 已通過(guò)
2018-01-03 13:39:10.973885+0800 GCD_Demo[1280:300474] 車1 開(kāi)始通過(guò)
2018-01-03 13:39:12.979111+0800 GCD_Demo[1280:300474] 車1 已通過(guò)
2018-01-03 13:39:12.979332+0800 GCD_Demo[1280:301301] 車3 開(kāi)始通過(guò)
2018-01-03 13:39:13.980507+0800 GCD_Demo[1280:301301] 車3 已通過(guò)
使用注意點(diǎn)
使用過(guò)程中避免在dispatch_semaphore_wait之前加入代碼
示例2: 信號(hào)量為2的時(shí)候,資源池的運(yùn)用
//value 有幾個(gè)車道
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(@"車1 開(kāi)始通過(guò)");
sleep(2);
NSLog(@"車1 已通過(guò)");
dispatch_semaphore_signal(semaphore);
});
//任務(wù)2
dispatch_async(quene, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"車2 開(kāi)始通過(guò)");
sleep(4);
NSLog(@"車2 已通過(guò)");
dispatch_semaphore_signal(semaphore);
});
//任務(wù)3
dispatch_async(quene, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"車3 開(kāi)始通過(guò)");
sleep(1);
NSLog(@"車3 已通過(guò)");
dispatch_semaphore_signal(semaphore);
});
輸出結(jié)果
2018-01-03 13:56:23.688576+0800 GCD_Demo[1363:365452] 車1 開(kāi)始通過(guò)
2018-01-03 13:56:23.688576+0800 GCD_Demo[1363:365436] 車2 開(kāi)始通過(guò)
2018-01-03 13:56:25.691141+0800 GCD_Demo[1363:365452] 車1 已通過(guò)
2018-01-03 13:56:25.691367+0800 GCD_Demo[1363:365435] 車3 開(kāi)始通過(guò)
2018-01-03 13:56:26.696554+0800 GCD_Demo[1363:365435] 車3 已通過(guò)
2018-01-03 13:56:27.690969+0800 GCD_Demo[1363:365436] 車2 已通過(guò)
從輸出結(jié)果中的時(shí)間中看出,同時(shí)使用了兩個(gè)資源,總耗時(shí)4s與預(yù)期結(jié)果一直。
總結(jié): dispatch_semaphore 適合做多線程的資源池相關(guān)的功能,不太不適合做多線程同步相關(guān)的功能