美文网首页
iOS-多线程中的信号量

iOS-多线程中的信号量

作者: doudo | 来源:发表于2017-09-25 13:45 被阅读16次

    网络请求的任务是提交给子线程异步处理了,对于主线程网络请求这样的任务也就快速执行完毕了,但是对于主线程网络请求是一个任务,处理收到的网络响应又是一个任务,注意不要把这两个过程混为一谈。

    我们在进行网络请求的过程中经常会遇到一个场景,就是需要刷新一个界面数据,而这个界面数据需要发起多个请求才能获得,例如:一个用户信息界面,包括基本数据,关联数据,其他特别数据等,这几种数据存在相互依赖的关系,并且获取每种数据的api不同,需要同时异步发起多个请求。在这种场景下面,就需要有一种线程同步机制来处理。通常多线程同步用得最多的就是信号量。不过,直接使用信号量不但代码上面相对松散,还会存在悬挂等问题。GCD已经提供了dispatch_group来很好的实现同步问题。
    下面我们就看看这两种方式:

    一、GCD的信号量 dispatch_semaphore_t

    思路,通过dispatch_group_notify来获取通知,那么必须保证网络请求回调都执行完之后接收到通知,这里是通过dispatch_semaphore来阻塞住group中的任务,直到网络请求返回以后再结束group。

    dispatch_group_t group = dispatch_group_create();
        
        dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
            dispatch_semaphore_t semaphore1 = dispatch_semaphore_create(0);
            //网络请求1
            [NetService getUserIconSuccess:^(id successData) {
                NSLog(@"----------finished");
                dispatch_semaphore_signal(semaphore1);
            } error:^(NSString *errorStr) {
                NSLog(@"----------finished");
                dispatch_semaphore_signal(semaphore1);
            }];
            dispatch_semaphore_wait(semaphore1, DISPATCH_TIME_FOREVER);
        });
        dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
            dispatch_semaphore_t semaphore2 = dispatch_semaphore_create(0);
            //网络请求2
            [NetService getUserIconSuccess:^(id successData) {
                NSLog(@"----------finished");
                dispatch_semaphore_signal(semaphore2);
            } error:^(NSString *errorStr) {
                NSLog(@"----------finished");
                dispatch_semaphore_signal(semaphore2);
            }];
            dispatch_semaphore_wait(semaphore2, DISPATCH_TIME_FOREVER);
        });
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            NSLog(@"两个网络请求都返回了");
        });
    

    二、dispatch_group_enter、dispatch_group_leave

    • dispatch_group_enter:增加当前group执行block数
    • dispatch_group_leave:减少当前group执行block数

    相当于通过我们手动调用enter和leave来告诉group中的是否执行结束了, enter告诉group增加了一个任务(可以通过引用计数更好理解,+1),leave告诉group结束了一个任务(-1),当group中没有任务了,就会执行dispatch_group_notify了。
    所以,enter和leave必须成对出现。

    dispatch_group_t group = dispatch_group_create();
        dispatch_group_enter(group);
        //网络请求1
        [NetService getUserIconSuccess:^(id successData) {
            NSLog(@"----------finished");
            dispatch_group_leave(group);
        } error:^(NSString *errorStr) {
            NSLog(@"----------finished");
            dispatch_group_leave(group);
        }];
        
        dispatch_group_enter(group);
        //网络请求2
        [NetService getUserIconSuccess:^(id successData) {
            NSLog(@"----------finished");
            dispatch_group_leave(group);
        } error:^(NSString *errorStr) {
            NSLog(@"----------finished");
            dispatch_group_leave(group);
        }];
        
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            NSLog(@"所有网络请求的数据都返回了");
        });
    

    相关文章

      网友评论

          本文标题:iOS-多线程中的信号量

          本文链接:https://www.haomeiwen.com/subject/epvrextx.html