前言
需求:有三个异步执行的任务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_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的区别
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]);
});
}










网友评论