dispatch_semaphore的主要作用 :
保持線程同步
為線程加鎖
主要方法:
dispatch_semaphore_t dispatch_semaphore_create(long value)
:方法接收一個long類型的參數, 返回參數中dispatch_semaphore_t類型的信號總量long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout)
:接收一個信號和時間值,若信號的信號量為0,則會阻塞當前線程,直到信號量大于0或者經過輸入的時間值;若信號量大于0,則會使信號量減1并返回,程序繼續住下執行long dispatch_semaphore_signal(dispatch_semaphore_t dsema)
:使信號量加1并返回
// 以打印100個數字為例
for (int i = 0; i < 100; i ++) {
NSLog(@"%i", i);
}
上述打印后會在控制臺中依次輸出1-100
- 用
dispatch_semaphore
讓線程加鎖
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
for (int i = 0; i < 100; i++) {
dispatch_async(queue, ^{
// 相當于加鎖
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"i = %zd semaphore = %@", i, semaphore);
NSLog(@"%d", i);
// 相當于解鎖
dispatch_semaphore_signal(semaphore);
});
}
分析:以上代碼首先創建一個隊列,隨后異步運行隊列,沒有加dispatch_semaphore
之前控制臺打印的數據順序不一,加上dispatch_semaphore
之后,會發現順序變一致了。因為加鎖進入
dispatch_semaphore_wait
的時候,信號量便會0,阻塞當前的線程,異步進入此命令的時候,無法繼續執行下一步,隨后到達dispatch_semaphore_signal
,信號量+1,此時線程通常,如此便可以為線程加鎖。
- 用dispatch_semaphore 每隔10秒打印順序不一的數字。
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);
for (int i = 0; i < 100; i ++) {
dispatch_group_async(group, queue, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"%d",i);
sleep(2);
dispatch_semaphore_signal(semaphore);
});
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
分析: 信號量為10,并發進入dispatch_semaphore_wait的時候,遞減到0, 隨后線程堵塞,sleep(2)中阻塞當前線程直到兩秒后dispatch_semaphore_signal依次遞增,并返回信號量,這樣就可以每隔10秒打印順序不一的數字。
dispatch_group_wait
會一直阻塞線程,直到 dispatch_group_t完成或者超時才會執行以下的代碼。