iOS 使用信号量来处理多图片上传

信号量就是一个资源计数器,对信号量有两个操作来达到互斥,分别是P和V操作。 一般情况是这样进行临界访问或互斥访问的: 设信号量值为1, 当一个进程1运行是,使用资源,进行P操作,即对信号量值减1,也就是资源数少了1个。这是信号量值为0。系统中规定当信号量值为0是,必须等待,知道信号量值不为零才能继续操作。 这时如果进程2想要运行,那么也必须进行P操作,但是此时信号量为0,所以无法减1,即不能P操作,也就阻塞。这样就到到了进程1排他访问。 当进程1运行结束后,释放资源,进行V操作。资源数重新加1,这是信号量的值变为1. 这时进程2发现资源数不为0,信号量能进行P操作了,立即执行P操作。信号量值又变为0.次数进程2咱有资源,排他访问资源。 这就是信号量来控制互斥的原理。

GCD如何使用信号量

我们使用GCD的时候如何让线程同步,目前我能想到的就三种

  • 1.dispatch_group
  • 2.dispatch_barrier
  • 3.dispatch_semaphore

1和2比较简单,也是比较常用的。这里不在介绍。如果不清楚可以参考并发其实很简单
这里主要讲讲dispatch_semaphore

在GCD中有三个函数是semaphore的操作,
分别是:  

  1. dispatch_semaphore_create 创建一个semaphore 
  2. dispatch_semaphore_signal 发送一个信号 
  3. dispatch_semaphore_wait 等待信号

简单的介绍一下这三个函数,第一个函数有一个整形的参数,我们可以理解为信号的总量,dispatch_semaphore_signal是发送一个信号,自然会让信号总量加1,dispatch_semaphore_wait等待信号,当信号总量少于0的时候就会一直等待,否则就可以正常的执行,并让信号总量-1,根据这样的原理,我们便可以快速的创建一个并发控制来同步任务和有限资源访问控制。

看代码

// 创建队列组
    dispatch_group_t group = dispatch_group_create();   
// 创建信号量,并且设置值为10
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(10);   
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);   
    for (int i = 0; i < 100; i++)   
    {   // 由于是异步执行的,所以每次循环Block里面的dispatch_semaphore_signal根本还没有执行就会执行dispatch_semaphore_wait,从而semaphore-1.当循环10此后,semaphore等于0,则会阻塞线程,直到执行了Block的dispatch_semaphore_signal 才会继续执行
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);   
        dispatch_group_async(group, queue, ^{   
            NSLog(@"%i",i);   
            sleep(2);   
// 每次发送信号则semaphore会+1,
            dispatch_semaphore_signal(semaphore);   
        });   
    }

上面的注释已经把如何通过控制信号量来控制线程同步解释的比较浅显了。关键就是这句:

// 由于是异步执行的,所以每次循环Block里面的dispatch_semaphore_signal根本还没有执行就会执行dispatch_semaphore_wait,从而semaphore-1.当循环10此后,semaphore等于0,则会阻塞线程,直到执行了Block的dispatch_semaphore_signal 才会继续执行

实际应用

在开发中我们需要等待某个网络回调完之后才执行后面的操作,根据啥给你们分析的过程,可以写出如下代码,达到这种效果。

_block BOOL isok = NO;  

    dispatch_semaphore_t sema = dispatch_semaphore_create(0);  
    Engine *engine = [[Engine alloc] init];  
    [engine queryCompletion:^(BOOL isOpen) {  
        isok = isOpen;  
        dispatch_semaphore_signal(sema);  
    } onError:^(int errorCode, NSString *errorMessage) {  
        isok = NO;  
        dispatch_semaphore_signal(sema);  
    }];  

    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);  
    // todo what you want to do after net callback

在具体一点,做通讯录的时候需要判断权限,才能获取通讯录。如果我没记错。再iOS9之前可以通过如下方式获得。这也是我第一次实际应用信号量的时候。
获取通讯录

//创建通讯簿的引用        
addBook=ABAddressBookCreateWithOptions(NULL, NULL);        //创建一个出事信号量为0的信号       
 dispatch_semaphore_t sema=dispatch_semaphore_create(0);        //申请访问权限       
 ABAddressBookRequestAccessWithCompletion(addBook, ^(bool greanted, CFErrorRef error)      
    {
            //greanted为YES是表示用户允许,否则为不允许           
 if (!greanted) {   
            tip=1;         
   }            //发送一次信号            dispatch_semaphore_signal(sema);  

     });        //等待信号触发     
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值