• GCD中的dispatch_semaphore的语法与作用 iOS


    (一)引入问题

    当并行执行的处理更新数据时,会产生数据不一致的情况,有时应用程序还会异常结束,虽然使用Serial Dipatch queue和dispatch_barrier_async函数可避免这类问题,但有必要进行更加细腻的排他控制

     1 /*!
     2  *  @brief  不考虑顺序,将所有数据添加到数组中
     3  */
     4 - (void)testError {
     5     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
     6     
     7     NSMutableArray *mArray = [NSMutableArray array];
     8     //当执行次数过大时,异常结束的概率很高
     9     for (int i = 0; i < 10000; i++) {
    10         
    11         dispatch_async(queue, ^{
    12             
    13             [mArray addObject:[NSNumber numberWithInt:i]];
    14         });
    15     }
    16     NSLog(@"%@", mArray);
    17     /*!
    18      *  @brief  运行结果
    19      *semaphore测试(3312,0x11ab21000) malloc: *** error for object 0x7f971c047000: pointer being freed was not allocated
    20      *** set a breakpoint in malloc_error_break to debug
    21      *  @return 异常结束
    22      */
    23 }

    (二)什么是dispatch_semaphore

    dispatch_semaphore是持有计数的信号,该计数是多线程编程中的计数类型信号,类似于过马路的信号灯,红灯表示不能通过,而绿灯表示可以通过

    而在dispatch_semaphore中使用计数来实现该功能,进行更细粒度的排他控制.

    在没有Serial Dispatch Queue和dispatch_barrier_async函数那么大的粒度且一部分处理需要进行排他控制的情况下,dispatch Semaphore便可发挥威力

    (三)dispatch_semaphore语法说明

    <1>通过dispatch_semaphore_create(long value);函数创建Dispatch_Semaphore,参数表示计数的初始值

    //参数说明

    //long value:表示计数的初始值

    dispatch_semaphore_t semaphore = dispatch_semaphore_create(long value);

    <2>dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);函数等待Dispatch Semaphore的计数值大于或者等于1,当满足条件时计数器执行减法,并从wait函数中返回

    ***当dispatch_semaphore_wait函数返回0时,可以安全地执行排他控制的处理

    //参数说明

    //dispatch_semaphore_t dsema:操作的Dispatch_Semaphore对象

    //dispatch_time_t timeout:由dispatch_time_t类型值指定等待时间

    dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);

    <3>dispatch_semaphore_signal(dispatch_semaphore_t dsema);函数将Dispatch_Semaphore的计数器加1

    //参数说明

    //dispatch_semaphore_t dsema:操作的Dispatch_Semaphore对象

    dispatch_semaphore_signal(dispatch_semaphore_t dsema);

    (三)代码演示

     1 /*!
     2  *  @brief  使用Dispatch Semaphore进行排他性控制
     3  */
     4 - (void)semaphoreSample {
     5     //1.创建全局队列
     6     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
     7     //2.创建dispatch_semaphore_t对象
     8     dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
     9     //3.创建保存数据的可变数组
    10     NSMutableArray *mArray = [NSMutableArray array];
    11     //执行10000次操作
    12     for (int i = 0; i < 10000; i++) {
    13         //异步添加数据
    14         dispatch_async(queue, ^{
    15             //数据进入,等待处理,信号量减1
    16             dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    17             //处理数据
    18             [mArray addObject:[NSNumber numberWithInt:i]];
    19             //数据处理完毕,信号量加1,等待下一次处理
    20             dispatch_semaphore_signal(semaphore);
    21         });
    22     }
    23     
    24     NSLog(@"%@", mArray);
    25     
    26     /*!
    27      *  @brief  执行结果
    28      *
    29      1
    30      2
    31      3
    32      ...
    33      9999
    34      *  @return 顺序输出,不会异常结束
    35      */
    36 }
  • 相关阅读:
    前端网络安全——其他安全问题
    前端网络安全——密码安全
    前端网络安全——接入层注入
    前端网络安全——点击劫持
    mac重装系统后安装列表
    manjaro踩坑记录
    JavaScript学习过程中遇到的一些坑
    JavaScript学习
    [解决方法] 如何在没有屏幕的情况下训练一些需要显示的程序
    Python中*号的作用详解
  • 原文地址:https://www.cnblogs.com/denz/p/5223117.html
Copyright © 2020-2023  润新知