使用 GCD 控制线程执行顺序

前言

需求:有三个异步执行的任务ABC任务 C 必须等待任务 A任务 B 执行完毕才执行。

本文分别采用三种方法来实现线程执行顺序的控制,semaphorebarriergroup。详细代码可以参考 WZHWaitThread

Semaphore

执行 dispatch_semaphore_wait 时,如果信号量大于 0,可以继续执行并把信号量减一;如果信号量小于等于 0,线程被阻塞,等待信号量大于 0dispatch_semaphore_signal 释放信号量,使信号量加一。dispatch_semaphore_waitdispatch_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 之后的的线程。这里注意两点:

  1. 在使用栅栏函数时,使用自定义的并行队列才有意义,如果用的是串行队列或者系统提供的全局并发队列,这个栅栏函数的作用等同于一个 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 the dispatch_sync function.

  1. dispatch_barrier_asyncdispatch_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]);
    });
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容