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!
可以看出,是每次请求完网络数据之后才执行处理网络数据逻辑,实现了拗口的“同步异步的操作”。
结语:
了解得更多,在写代码的时候可以有更多的解决方案可供选择,就更有可能写出优雅的代码!