(一)引入问题

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

 /*!
* @brief 不考虑顺序,将所有数据添加到数组中
*/
- (void)testError {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ); NSMutableArray *mArray = [NSMutableArray array];
//当执行次数过大时,异常结束的概率很高
for (int i = ; i < ; i++) { dispatch_async(queue, ^{ [mArray addObject:[NSNumber numberWithInt:i]];
});
}
NSLog(@"%@", mArray);
/*!
* @brief 运行结果
*semaphore测试(3312,0x11ab21000) malloc: *** error for object 0x7f971c047000: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
* @return 异常结束
*/
}

(二)什么是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);

(三)代码演示

 /*!
* @brief 使用Dispatch Semaphore进行排他性控制
*/
- (void)semaphoreSample {
//1.创建全局队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, );
//2.创建dispatch_semaphore_t对象
dispatch_semaphore_t semaphore = dispatch_semaphore_create();
//3.创建保存数据的可变数组
NSMutableArray *mArray = [NSMutableArray array];
//执行10000次操作
for (int i = ; i < ; i++) {
//异步添加数据
dispatch_async(queue, ^{
//数据进入,等待处理,信号量减1
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
//处理数据
[mArray addObject:[NSNumber numberWithInt:i]];
//数据处理完毕,信号量加1,等待下一次处理
dispatch_semaphore_signal(semaphore);
});
} NSLog(@"%@", mArray); /*!
* @brief 执行结果
*
1
2
3
...
9999
* @return 顺序输出,不会异常结束
*/
}

GCD中的dispatch_semaphore的语法与作用的更多相关文章

  1. GCD中的dispatch_apply的用法及作用

    GCD中的dispatch_apply的用法及作用 (一)dispatch_apply的基本用法 dispatch_apply函数是dispatch_sync函数和Dispatch Group的关联A ...

  2. GCD中的dispatch_set_target_queue的用法及作用

    (一),使用dispatch_set_target_queue更改Dispatch Queue的执行优先级 dispatch_queue_create函数生成的DisPatch Queue不管是Ser ...

  3. 详解jquery插件中(function ( $, window, document, undefined )的作用。

    1.(function(window,undefined){})(window); Q:(function(window,undefined){})(window);中为什么要将window和unde ...

  4. 如何在Visual Studio 2017中使用C# 7+语法 构建NetCore应用框架之实战篇(二):BitAdminCore框架定位及架构 构建NetCore应用框架之实战篇系列 构建NetCore应用框架之实战篇(一):什么是框架,如何设计一个框架 NetCore入门篇:(十二)在IIS中部署Net Core程序

    如何在Visual Studio 2017中使用C# 7+语法   前言 之前不知看过哪位前辈的博文有点印象C# 7控制台开始支持执行异步方法,然后闲来无事,搞着,搞着没搞出来,然后就写了这篇博文,不 ...

  5. bootstrap中table的colspan不起作用

    bootstrap中table的colspan不起作用,即在不指定宽度的条件下,各个td宽度不符合colspan指定的宽度. 添加table0layout:fixed后显示正常. table{ tab ...

  6. jquery 中的 return false 不起作用

    jquery  中的 return false 不起作用 $(".lcId").each(function(e) { if ($(this).attr("checked& ...

  7. iOS 关于GCD中的队列

    GCD中队列分类及获得方式 1.串行队列  dispatch_queue_t queue = dispatch_queue_create("队列名", DISPATCH_QUEUE ...

  8. GCD中使用dispatch_after函数延迟处理任务

    在实际的开发中,经常会遇到想要在指定的时间间隔后执行某个处理 <一>在GCD中提供了dispatch_after函数来完成这一操作 dispatch_after(dispatch_time ...

  9. spring中的BeanFactory与ApplicationContext的作用和区别?

    BeanFactory类关系继承图 1. BeanFactory类结构体系: BeanFactory接口及其子类定义了Spring IoC容器体系结构,由于BeanFactory体系非常的庞大和复杂, ...

随机推荐

  1. mvc4.0添加EF4.0时发生编译时错误

    解决此问题是因为MVC4.0默认未添加EF4.0的引用,EF4.0引用的是System.Data.Entity.dll, Version=4.0.0.0, 解决办法: 在web.config文件sys ...

  2. NVIDIA CuDNN 安装说明

    CuDNN是专门针对Deep Learning框架设计的一套GPU计算加速方案,目前支持的DL库包括Caffe,ConvNet, Torch7等. CuDNN可以在官网免费获得,注册帐号后即可下载.官 ...

  3. ruby -- 基础学习(六)时间计算

    计算下一天的这个时刻, # 比如"2013-8-16 18:45:12" 的下一天的这个时刻 “2013-8-17 18:45:12” Time.now + 1.day 如果想得到 ...

  4. CentOS 6.4 编译安装LLVM3.3,Clang和Libc++

    LLVM的最新版本3.3终于在6月17日发布了,按之前的计划6月5日就应该发布了,不过毕竟没有太晚,赶在VS2013 preview(6月26日微软Build大会)之前出来了.加上之前gcc4.8.1 ...

  5. linux根目录下文件夹概览

    / 根目录 /bin 存放必要的命令 /boot 存放内核以及启动所需的文件等 /dev 存放设备文件 /etc 存放系统的配置文件 /home 用户文件的主目录,用户数据存放在其主目录中 /lib ...

  6. Linux内核知识

    版本 linus树 Linux内核最初创始人--Linus Torvalds管理一个Linus树,linus树也称为主线(mainline).一般指的upstream,"上游",也 ...

  7. Windows平台下ActiveMQ 安装

    安装之前需要先确定机器上已经有JVM环境,如果没有则会在安装过程中提示 Unable to execute Java command.  系统找不到指定的文件 第一步:从官网下载ActiveMQ的安装 ...

  8. Gradle学习系列之九——自定义Task类型

    在本系列的上篇文章中,我们学习了多Project构建,在本篇文章中,我们将学到如何自定义Task类型. 请通过以下方式下载本系列文章的Github示例代码: git clone https://git ...

  9. EL表达式经典用法

    1.EL表达式获取list集合length长度: <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix=&quo ...

  10. istView的项移除

    如标题所言,是做删除ListView绑定项的功能的:鉴于这个功能当时确实花费了很多时间,并且网上也找不到删除所需的案例,所以,我就做了一份案例,仅供各位前辈和同行进行参考,如有不当之处,还望指点,我将 ...