iOS基础之----GCD多线程同步机制

来源:互联网 发布:最新淘宝怎么查总消费 编辑:程序博客网 时间:2024/05/21 07:05

一、场景

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

二、实现方式

在上述场景中,使用dispatch_group一般流程如下:

     1、创建一个group:

          dispatch_group_t group = dispatch_group_create();

     2、把一个异步操作加入到group中

           dispatch_group_enter(group);
           dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

                *
                dispatch_group_leave(group);
           });

     3、等待group完成所有异步操作

          dispatch_group_notify(group, dispatch_get_main_queue(), ^{

          });

三、说明

  • dispatch_group_notify:当group中所有的block操作都完成后才会执行,不会阻塞当前调用线程,如果需要阻塞当前调用线程,可使用dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
  • dispatch_group_enter:增加当前group执行block数
  • dispatch_group_leave:减少当前group执行block数

四、注意事项

  • dispatch_group_enterdispatch_group_leave必须成对出现
  • ios6.0及以下系统版本需要手动管理dispatch_group对象生命周期,dispatch_retaindispatch_release

五、关于信号量,可以用停车来比喻

  停车场剩余4个车位,那么即使同时来了四辆车也能停的下。如果此时来了五辆车,那么就有一辆需要等待。

  信号量的值就相当于剩余车位的数目,dispatch_semaphore_wait函数就相当于来了一辆车,dispatch_semaphore_signal

  就相当于走了一辆车。停车位的剩余数目在初始化的时候就已经指明了(dispatch_semaphore_create(long value)),

  调用一次dispatch_semaphore_signal,剩余的车位就增加一个;调用一次dispatch_semaphore_wait剩余车位就减少一个;

  当剩余车位为0时,再来车(即调用dispatch_semaphore_wait)就只能等待。有可能同时有几辆车等待一个停车位。有些车主

  没有耐心,给自己设定了一段等待时间,这段时间内等不到停车位就走了,如果等到了就开进去停车。而有些车主就像把车停在这,

  所以就一直等下去。

六、一个下载的例子

dispatch_semaphore_t semaphore =dispatch_semaphore_create(3);
    
    dispatch_group_t dispatchGroup =dispatch_group_create();
    
    for (int i =0; i < 10; i++) {
        
        NSLog(@"i is %d",i);
        NSURLSession *session = [NSURLSessionsharedSession];
        
        NSURL *url = [NSURLURLWithString:@"https://codeload.github.com/EricForGithub/SalesforceReactDemo/zip/master"];
        
        NSURLSessionDownloadTask *sessionDownloadTask =[sessiondownloadTaskWithURL:url completionHandler:^(NSURL *_Nullable location, NSURLResponse * _Nullable response,NSError * _Nullable error) {
            
            sleep(5.0);
            
            NSLog(@"release a signal");
            
            dispatch_group_leave(dispatchGroup);
            dispatch_semaphore_signal(semaphore);
            
            
        }];
        
        dispatch_group_enter(dispatchGroup);//为了所有下载完成后能调用函数,引入 dispatch group。如果信号量是1的话,可以不使用这个机制,也能达到效果。
        dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER); //为了最大并发数,加入信号量机制
        
        [sessionDownloadTask resume];
        
    }
    
    dispatch_group_notify(dispatchGroup,dispatch_get_main_queue(), ^(){
        NSLog(@"end--全部下载结束咯");
    });


















原创粉丝点击