多线程GCD之dispatch_semaphore_t

/*
 * 线程并发操作,意思就是说你开辟的这个线程里面最大允许的并行队列数是多少,那么实际超出的的部分队列就必须等待。
 * dispatch_semaphore_create(para):创建一个信号量,参数是并发的初始值
 * dispatch_semaphore_signal:发送一个信号量,表示我即将离开这个队列,通知等待着你可以准备进入
 * dispatch_semaphore_wait:等待信号,表示前面的并行队列已经满了,我现在只能等待(dispatch_semaphore_signal离开并发送我可以进入的信号
 * 应用场景:我一般在做网络请求时,后边的一个请求必须依赖上一个请求的结果才能请求时,就使用semaphore,使其初值为1,感觉有点大材小用
 */
- (IBAction)semaphore:(id)sender {

    // 创建线程组
    dispatch_group_t group = dispatch_group_create();
    // 创建sempahore 并发量是5,最多允许5个队列同时进行操作,那么剩下的只能等待了
    static int number = 5;
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(number);
    // 在全局队列里面申请一个队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    // 循环创建多个线程
    for (int i =0; i<50; i++) {

        /* dispatch_semaphore_wait(<#dispatch_semaphore_t  _Nonnull dsema#>, <#dispatch_time_t timeout#>)
         * para1: 声明的信号变量
         * para2: 等待的级别
                    DISPATCH_TIME_NOW (0ull) 只是当下等待一下
                    DISPATCH_TIME_FOREVER (~0ull) 永远等待
         */

        // 等待下面异步线程的耗时操作,一般是网路请求
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        dispatch_group_async(group, queue, ^{

            sleep(3);

            // 表示我操作完了,通知下一个等待着,你可以进来了
            dispatch_semaphore_signal(semaphore);
            NSLog(@"并发量减1,通知下一位");
        });
        NSLog(@"并发数:%d",number);
        number --;
    }

    // 这句话的意思是,保证线程组里面的所有线程执行完后才能进行下一步
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

    dispatch_group_notify(group, queue, ^{
        NSLog(@"处理完了");
    });

}
结果:

2017-03-24 13:03:55.178658 test[11558:2489245] 并发数:5
2017-03-24 13:03:55.178967 test[11558:2489245] 并发数:4
2017-03-24 13:03:55.179127 test[11558:2489245] 并发数:3
2017-03-24 13:03:55.179278 test[11558:2489245] 并发数:2
2017-03-24 13:03:55.179428 test[11558:2489245] 并发数:1
2017-03-24 13:03:58.181634 test[11558:2489245] 并发数:0
2017-03-24 13:03:58.181716 test[11558:2489265] 并发量减1,通知下一位
2017-03-24 13:03:58.182000 test[11558:2489264] 并发量减1,通知下一位
2017-03-24 13:03:58.182046 test[11558:2489245] 并发数:-1
2017-03-24 13:03:58.182297 test[11558:2489245] 并发数:-2
2017-03-24 13:03:58.182492 test[11558:2489317] 并发量减1,通知下一位
2017-03-24 13:03:58.182546 test[11558:2489245] 并发数:-3
2017-03-24 13:03:58.182743 test[11558:2489309] 并发量减1,通知下一位
2017-03-24 13:03:58.184749 test[11558:2489245] 并发数:-4

上面的打印结果,刚开始同步创建5个并发的操作,当然在建立这5个并发操作时,耗时操作里面的代码也是在执行的,当5g个并发量够了时,for循环就会阻塞,开始等待某个semaphore完成耗时操作,这时循环又会进行一次。这就是控制并发量为5个线程的操作
引用别人的介绍:

简单的介绍一下这一段代码,创建了一个初使值为5的semaphore,每一次for循环都会创建一个新的线程,线程结束的时候会发送一个信号,线程创建之前会信号等待,所以当同时创建了5个线程之后,for循环就会阻塞,等待有线程结束之后会增加一个信号才继续执行,如此就形成了对并发的控制,如上就是一个并发数为5的一个线程队列。

关于信号量,借用别人的一个例子:一般可以用停车来比喻。

  停车场剩余4个车位,那么即使同时来了四辆车也能停的下。如果此时来了五辆车,那么就有一辆需要等待。信号量的值就相当于剩余车位的数目,dispatch_semaphore_wait函数就相当于来了一辆车,dispatch_semaphore_signal。就相当于走了一辆车。停车位的剩余数目在初始化的时候就已经指明了(dispatch_semaphore_create(value:Int))),调用一次dispatch_semaphore_signal,剩余的车位就增加一个;调用一次dispatch_semaphore_wait剩余车位就减少一个;当剩余车位为0时,再来车(即调用dispatch_semaphore_wait)就只能等待。有可能同时有几辆车等待一个停车位。有些车主。没有耐心,给自己设定了一段等待时间,这段时间内等不到停车位就走了,如果等到了就开进去停车。而有些车主就像把车停在这,所以就一直等下去。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值