dispatch_semaphore信号量用法

2017-01-04  本文已影响624人  一叶菜

关于多线程的并发,我们可能会选择使用NSOperationQueue来处理,那么在GCD中如何处理多线程的并发呢?就是dispatch_semaphore
 
在GCD中有三个函数是semaphore的操作,分别是:
  dispatch_semaphore_create   创建一个semaphore
  dispatch_semaphore_signal   发送一个信号
  dispatch_semaphore_wait    等待信号

第一个函数有一个整形的参数,我们可以理解为信号的总量,dispatch_semaphore_signal是发送一个信号,自然会让信号总量加1,dispatch_semaphore_wait等待信号,当信号总量少于0的时候就会一直等待,如果线程在一个信号量上等待时,线程会被阻塞(如果有必要的话),直至计数器大于零,然后就可以正常的执行,并让信号总量-1,根据这样的原理,我们便可以快速的创建一个并发控制来同步任务和有限资源访问控制。

信号量在多线程开发中被广泛使用,当一个线程在进入一段关键代码之前,线程必须获取一个信号量,一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待前面的线程释放信号量。

信号量的具体做法是:当信号计数大于0时,每条进来的线程使计数减1,直到变为0,变为0后其他的线程将进不来,处于等待状态;执行完任务的线程释放信号,使计数加1,如此循环下去。

-(void)loginRequest
{
    NSLog(@"进入登录请求");
    dispatch_semaphore_t loginSem = dispatch_semaphore_create(0);
    
    NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
    NSString *name = [userDefault objectForKey:@"UserName"];
    NSString *psw = [userDefault objectForKey:@"Password"];
    
    if (name && psw)
    {
        
      //url 登录请求接口 回调后做登录成功与失败的处理 并释放信号量
//        [self createLoginRequest:name password:psw completion:^(id response, NSString *error) {
        
//             self.loginStatus = error == nil ? true : false;
            NSLog(@"登录返回");
            dispatch_semaphore_signal(loginSem);
//        }];
        
    } else {
        //登录失败的处理
        //self.loginStatus == false
        dispatch_semaphore_signal(loginSem);
    }
    // 等待重登录信号
    NSLog(@"等待登录信号");
    dispatch_semaphore_wait(loginSem, DISPATCH_TIME_FOREVER);
    
    NSLog(@"通过登录信号,继续执行");
    
//    if (self.loginStatus == false)
//    {
//        if (block) block(nil, @"登录失败, 请重新登录");    // 收到登录失败的,弹个提醒
//        return ;
//    } else {
//        NSLog(@"登录成功");
//    }

}
上面是登录请求的例子,请求前创建信号量为0,然后做登录请求,当登录请求处理完后,释放信号量,
才会执行`通过登录信号,继续执行`。否则没有释放信号,信号量为0,会一直等待直到其释放。

参考

GCD 信号量控制并发 (dispatch_semaphore)

上一篇下一篇

猜你喜欢

热点阅读