美文网首页
iOS-OC 关于信号量 dispatch_semaphore_

iOS-OC 关于信号量 dispatch_semaphore_

作者: 洧中苇_4187 | 来源:发表于2020-05-21 15:59 被阅读0次

    线程同步方案

    一.说明

    dispatch_semaphore_t dispatch_semaphore_create(long value);
    
    关于这个函数 我先贴张图,方便说明问题 image.png

    参数:

    信号量的初始值不要传一个小于0的值

    返回值:

    一个新创建的信号量

    细节讨论:

    Passing zero for the value is useful for when two threads need to reconcile 
    the completion of a particular event. Passing a value greater than zero is
     useful for managing a finite pool of resources, where the pool size is equal 
    to the value.
    
    翻译:
    当两个线程需要协调特定事件的完成时,传递零是很有用的。
    传递大于零的值对于管理有限的资源池非常有用,其中池大小等于该值。
    

    注意点

    Calls to dispatch_semaphore_signal must be balanced with calls to wait().
     Attempting to dispose of a semaphore with a count lower than value 
    causes an EXC_BAD_INSTRUCTION exception.
    
    翻译:
    对dispatch_semaphore_signal的调用必须与对wait()的调用进行平衡。
    试图以低于值的计数来处理信号量会导致EXC_BAD_INSTRUCTION异常。
    也就是说 "dispatch_semaphore_signal" 和 "dispatch_semaphore_wait"必须一一匹配,
    如果不匹配,就会报"EXC_BAD_INSTRUCTION"这个错误
    

    二. 使用

    1> 它能够使异步线程的执行顺序按照想要的顺序执行,这个特性有点像dispatch_group_create, dispatch_group_notify 和栅栏函数dispatch_barrier_sync
    2> 它还有一个应用场景 加锁,多条线程访问读写同一数据时,会出现数据错乱的情况,在写之前加一把🔐

    代码简单,示例如下:

    当把加解锁的代码注释时,三个任务顺序可能随机执行,并且是开启新的线程,因为是异步+并发;
    当打开加解锁代码时,有开启新线程的能力,但它会按顺序执行.

    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        dispatch_semaphore_t signalSema = dispatch_semaphore_create(0);
    
        //异步并行-开启多条线程
    //    dispatch_queue_t myqueue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_SERIAL);//异步+串行,开启一条子线程,执行
    
        dispatch_queue_t myqueue = dispatch_queue_create("myqueue", DISPATCH_QUEUE_CONCURRENT);//异步+并发,开启多条线程
    //    dispatch_queue_t myqueue = dispatch_get_global_queue(0, 0);//异步+并发,开启多条线程
    //    dispatch_queue_t myqueue = dispatch_get_main_queue();//异步串行队列,主线程执行,一个个执行
        
    //    dispatch_semaphore_wait(signalSema, DISPATCH_TIME_FOREVER);
        dispatch_async(myqueue, ^{
                NSLog(@"任务1-%@",[NSThread currentThread]);
            dispatch_semaphore_signal(signalSema);
        });
        
        dispatch_semaphore_wait(signalSema, DISPATCH_TIME_FOREVER);
    
        dispatch_async(myqueue, ^{
                NSLog(@"任务2-%@",[NSThread currentThread]);
                dispatch_semaphore_signal(signalSema);
        });
        
        dispatch_semaphore_wait(signalSema, DISPATCH_TIME_FOREVER);
      
        dispatch_async(myqueue, ^{
                NSLog(@"任务3-%@",[NSThread currentThread]);
                dispatch_semaphore_signal(signalSema);
            
        });
    
        NSLog(@"\n");
    
    }
    

    这个的应用,在MJExtension有详细使用,有兴趣的可自行查看

    #ifndef MJ_LOCK
    #define MJ_LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
    #endif
    
    #ifndef MJ_UNLOCK
    #define MJ_UNLOCK(lock) dispatch_semaphore_signal(lock);
    #endif
    
    // 信号量
    #define MJExtensionSemaphoreCreate \
    static dispatch_semaphore_t signalSemaphore; \
    static dispatch_once_t onceTokenSemaphore; \
    dispatch_once(&onceTokenSemaphore, ^{ \
       signalSemaphore = dispatch_semaphore_create(1); \
    });
    

    总结

    1.当多条线程时,传入 0比较合适dispatch_semaphore_create,
    2.dispatch_semaphore_signaldispatch_semaphore_wait必须一一对应,如果不对应会报错EXC_BAD_INSTRUCTION.

    1. dispatch_semaphore_signal 调用一次,信号量+1, dispatch_semaphore_wait 调用一次,信号量-1,当信号量 <0时,当前线程就会卡主,没法往下执行,直到dispatch_semaphore_signal被调用,使得信号量+1,才会继续往下执行.

    相关文章

      网友评论

          本文标题:iOS-OC 关于信号量 dispatch_semaphore_

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