前言
需求:有三个异步执行的任务A
、B
、C
,任务 C
必须等待任务 A
和 任务 B
执行完毕才执行。
本文分别采用三种方法来实现线程执行顺序的控制,semaphore
、barrier
、group
。详细代码可以参考 WZHWaitThread。
Semaphore
执行 dispatch_semaphore_wait
时,如果信号量大于 0
,可以继续执行并把信号量减一;如果信号量小于等于 0
,线程被阻塞,等待信号量大于 0
。dispatch_semaphore_signal
释放信号量,使信号量加一。dispatch_semaphore_wait
和 dispatch_semaphore_signal
配合使用可以控制线程的执行。
- (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 必须成对使用
});
NSLog(@"Wait Thread Test.");
}
Barrier
dispatch_barrier_async
可以拦截线程的执行,在 dispatch_barrier_async
之前的线程执行完才会执行 dispatch_barrier_async
之后的的线程。这里注意两点:
- 在使用栅栏函数时,使用自定义的并行队列才有意义,如果用的是串行队列或者系统提供的全局并发队列,这个栅栏函数的作用等同于一个
dispatch_sync
的作用。
The queue you specify should be a concurrent queue that you create yourself using the
dispatch_queue_create
function. If the queue you pass to this function is a serial queue or one of the global concurrent queues, this function behaves like thedispatch_sync
function.
-
dispatch_barrier_async
与dispatch_barrier_sync
的区别
dispatch_barrier_sync
需要等待自己的任务结束之后才会继续程序,然后执行后面的任务;
dispatch_barrier_async
将自己的任务插入到 queue
之后,不会等待自己的任务结束,会继续把后面的任务插入到 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
可以把相关的任务归并到一个组内来执行,通过监听组内所有任务的执行情况来做相应处理。待任务组执行完毕时调用 dispatch_group_notify
,不会阻塞当前线程。或者 dispatch_group_wait
可以等待组任务完成,会阻塞当前线程,当任务组执行完毕时,才会解除阻塞当前线程。
注意:不要在主线程使用 dispatch_group_wait
,如果 group
中如果添加主队列后再使用 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]);
});
}