美文网首页
iOS 信号量详解

iOS 信号量详解

作者: MiniCoder | 来源:发表于2020-03-12 16:37 被阅读0次

    信号量

    信号量是用于多线程同步的,跟锁不一样的是,信号量不一定是锁定某一个资源,而是流程上的概念,比如:有A,B两个线程,B线程要等A线程完成某一任务以后再进行自己下面的步骤,这个任务 并不一定是锁定某一资源,还可以是进行一些计算或者数据处理之类。而对于锁来说,锁住的资源无法被其余的线程访问,从而阻塞线程而实现线程同步。

    gcd的信号量主要有3个函数,分别为

    创建一个值为M的信号量
    dispatch_semaphore_create(long value);
    
    如果该信号量的值大于0,则使其信号量的值-1,否则,阻塞线程直到该信号量的值大于0或者达到等待时间。
    dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);
    
    释放信号量,使得该信号量的值加1
    dispatch_semaphore_signal(dispatch_semaphore_t dsema);
    

    限制线程的最大并发数

    dispatch_semaphore_t sema = dispatch_semaphore_create(M);
    for (NSInteger i = 0;i<N;i++) {
         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); 
            // doing
            dispatch_semaphore_signal(sema);
        });
    } 
    

    如上述代码可知,总共异步执行N个任务,但是由于我们设置了值为M的信号量,每一次执行任务的时候都会导致信号量的减1,而在任务结束后使信号量加1,当信号量减到0的时候,说明正在执行的任务有M个,这个时候其它任务就会阻塞,直到有任务被完成时,这些任务才会执行。
    阻塞发请求的线程
    有些时候,我们需要阻塞发送请求的线程,比如在多个请求回调后统一操作的需求,而这些请求之间并没有顺序关系,且这些接口都会另开线程进行网络请求的。一般地,这种多线程完成后进行统一操作的需求都会使用队列组(dispatch_group_t)来完成,但是由于是异步请求,没等其异步回调之后,请求的线程就结束了,为此,就需要使用信号量来阻塞住发请求的线程。实现代码如下:

    dispatch_async(queue, 0), ^{
        dispatch_semaphore_t sema = dispatch_semaphore_create(0);
        [网络请求:^{
            //请求回调
            dispatch_semaphore_signal(sema);  
        }];
        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    });
    

    这样,请求的线程就可以等到回调结束后再结束了,再配合队列组就能完成上述的需求。这种技巧可用于以下场景:
    多个请求结束后统一操作
    多个请求顺序执行

    相关文章

      网友评论

          本文标题:iOS 信号量详解

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