iOS DeveloperiOS开发基础知识

GCD semaphore 的两种使用场景

2019-01-12  本文已影响3人  永远保持一颗进取心

semaphore 的 3 个相关 GCD 接口

创建信号量
dispatch_semaphore_t dispatch_semaphore_create(long value)

信号量 -1
long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);

信号量 +1
long dispatch_semaphore_signal(dispatch_semaphore_t dsema);

更加详细请看苹果官方文档

1.控制并发数量

这个场景比较好理解,就是某种资源有限,需要控制同时访问线程的数量。

举个栗子

#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //资源数
        long resourceCount = 2;
        //信号量对象
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(resourceCount);
        
        
        void (^block)(void) = ^{
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            NSLog(@"start task on thread: %@", [NSThread currentThread].name);
            sleep(2);
            NSLog(@"complete task on thread: %@", [NSThread currentThread].name);
            dispatch_semaphore_signal(semaphore);
        };
        
        //新建三个 thread 并 start
        NSThread *ta = [[NSThread alloc] initWithBlock:block];
        ta.name = @"a";
        NSThread *tb = [[NSThread alloc] initWithBlock:block];
        tb.name = @"b";
        NSThread *tc = [[NSThread alloc] initWithBlock:block];
        tc.name = @"c";
        [ta start];
        [tb start];
        [tc start];
        
        sleep(8);//防止 主线程 结束而退出 进程
        
    }
    return 0;
}

日志打印

//剔除了无用的信息
21:52:18.394813+0800 start task on thread: a
21:52:18.394870+0800 start task on thread: b
21:52:20.400053+0800 complete task on thread: a
21:52:20.400056+0800 complete task on thread: b
21:52:20.400243+0800 start task on thread: c
21:52:22.402126+0800 complete task on thread: c

这里限制的资源数量是 2, 我们可以看到线程 a 和 b 的开始执行和完成时间几乎是相同的。然而,线程 c 的执行要延后 2s。

2.同步异步的操作

这个场景对自己来说理解得没有第 1 点好理解。
“同步异步的操作” 有点拗口,举个栗子

int main(int argc, const char * argv[]) {
    @autoreleasepool {
            // 参数传 0
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
        
        //异步请求网络数据
        dispatch_queue_t concurrentQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)),concurrentQ, ^{
            NSLog(@"request network data!");
            dispatch_semaphore_signal(semaphore);
        });
        
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        
        //处理网络数据
        NSLog(@"handle network!");
        
        //其他逻辑
    }
    return 0;
}

日志打印

request network data!
handle network!

可以看出,是每次请求完网络数据之后才执行处理网络数据逻辑,实现了拗口的“同步异步的操作”。

结语:
了解得更多,在写代码的时候可以有更多的解决方案可供选择,就更有可能写出优雅的代码!

上一篇 下一篇

猜你喜欢

热点阅读