
前言
需求:有三個(gè)異步執(zhí)行的任務(wù)A、B、C,任務(wù) C 必須等待任務(wù) A 和 任務(wù) B 執(zhí)行完畢才執(zhí)行。
本文分別采用三種方法來實(shí)現(xiàn)線程執(zhí)行順序的控制,semaphore、barrier、group。詳細(xì)代碼可以參考 WZHWaitThread。
Semaphore
執(zhí)行 dispatch_semaphore_wait 時(shí),如果信號(hào)量大于 0,可以繼續(xù)執(zhí)行并把信號(hào)量減一;如果信號(hào)量小于等于 0,線程被阻塞,等待信號(hào)量大于 0。dispatch_semaphore_signal 釋放信號(hào)量,使信號(hào)量加一。dispatch_semaphore_wait 和 dispatch_semaphore_signal 配合使用可以控制線程的執(zhí)行。
- (void)waitThreadWithSemaphore {
dispatch_queue_t currentQueue = dispatch_queue_create("current queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
dispatch_async(currentQueue, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"Thread A %@", [NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
});
dispatch_async(currentQueue, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"Thread B %@", [NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
});
dispatch_async(currentQueue, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"Thread C %@", [NSThread currentThread]);
dispatch_semaphore_signal(semaphore);
dispatch_semaphore_signal(semaphore);
// dispatch_semaphore_wait 和 dispatch_semaphore_signal 必須成對(duì)使用
});
NSLog(@"Wait Thread Test.");
}
Barrier
dispatch_barrier_async 可以攔截線程的執(zhí)行,在 dispatch_barrier_async 之前的線程執(zhí)行完才會(huì)執(zhí)行 dispatch_barrier_async 之后的的線程。這里注意兩點(diǎn):
- 在使用柵欄函數(shù)時(shí),使用自定義的并行隊(duì)列才有意義,如果用的是串行隊(duì)列或者系統(tǒng)提供的全局并發(fā)隊(duì)列,這個(gè)柵欄函數(shù)的作用等同于一個(gè)
dispatch_sync的作用。
The queue you specify should be a concurrent queue that you create yourself using the
dispatch_queue_createfunction. If the queue you pass to this function is a serial queue or one of the global concurrent queues, this function behaves like thedispatch_syncfunction.
-
dispatch_barrier_async與dispatch_barrier_sync的區(qū)別
dispatch_barrier_sync 需要等待自己的任務(wù)結(jié)束之后才會(huì)繼續(xù)程序,然后執(zhí)行后面的任務(wù);
dispatch_barrier_async 將自己的任務(wù)插入到 queue 之后,不會(huì)等待自己的任務(wù)結(jié)束,會(huì)繼續(xù)把后面的任務(wù)插入到 queue。
- (void)waitThreadWithBarrier {
dispatch_queue_t queue = dispatch_queue_create("current queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"Thread A %@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"Thread B %@", [NSThread currentThread]);
});
dispatch_barrier_sync(queue, ^{
NSLog(@"barrier %@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"Thread C %@", [NSThread currentThread]);
});
NSLog(@"Wait Thread Test In %@", [NSThread currentThread]);
}
Group
dispatch_group 可以把相關(guān)的任務(wù)歸并到一個(gè)組內(nèi)來執(zhí)行,通過監(jiān)聽組內(nèi)所有任務(wù)的執(zhí)行情況來做相應(yīng)處理。待任務(wù)組執(zhí)行完畢時(shí)調(diào)用 dispatch_group_notify,不會(huì)阻塞當(dāng)前線程。或者 dispatch_group_wait 可以等待組任務(wù)完成,會(huì)阻塞當(dāng)前線程,當(dāng)任務(wù)組執(zhí)行完畢時(shí),才會(huì)解除阻塞當(dāng)前線程。
注意:不要在主線程使用 dispatch_group_wait,如果 group 中如果添加主隊(duì)列后再使用 dispatch_group_wait 有可能引起死鎖。
- (void)waitThreadWithGroup {
dispatch_queue_t queue = dispatch_queue_create("current queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
NSLog(@"Thread A %@", [NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
NSLog(@"Thread B %@", [NSThread currentThread]);
});
dispatch_group_notify(group, queue, ^{
NSLog(@"Thread C %@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"Wait Thread Test In %@", [NSThread currentThread]);
});
}