GCD中的dispatch_semaphore的语法与作用
(一)引入问题
当并行执行的处理更新数据时,会产生数据不一致的情况,有时应用程序还会异常结束,虽然使用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的语法与作用的更多相关文章
- GCD中的dispatch_apply的用法及作用
GCD中的dispatch_apply的用法及作用 (一)dispatch_apply的基本用法 dispatch_apply函数是dispatch_sync函数和Dispatch Group的关联A ...
- GCD中的dispatch_set_target_queue的用法及作用
(一),使用dispatch_set_target_queue更改Dispatch Queue的执行优先级 dispatch_queue_create函数生成的DisPatch Queue不管是Ser ...
- 详解jquery插件中(function ( $, window, document, undefined )的作用。
1.(function(window,undefined){})(window); Q:(function(window,undefined){})(window);中为什么要将window和unde ...
- 如何在Visual Studio 2017中使用C# 7+语法 构建NetCore应用框架之实战篇(二):BitAdminCore框架定位及架构 构建NetCore应用框架之实战篇系列 构建NetCore应用框架之实战篇(一):什么是框架,如何设计一个框架 NetCore入门篇:(十二)在IIS中部署Net Core程序
如何在Visual Studio 2017中使用C# 7+语法 前言 之前不知看过哪位前辈的博文有点印象C# 7控制台开始支持执行异步方法,然后闲来无事,搞着,搞着没搞出来,然后就写了这篇博文,不 ...
- bootstrap中table的colspan不起作用
bootstrap中table的colspan不起作用,即在不指定宽度的条件下,各个td宽度不符合colspan指定的宽度. 添加table0layout:fixed后显示正常. table{ tab ...
- jquery 中的 return false 不起作用
jquery 中的 return false 不起作用 $(".lcId").each(function(e) { if ($(this).attr("checked& ...
- iOS 关于GCD中的队列
GCD中队列分类及获得方式 1.串行队列 dispatch_queue_t queue = dispatch_queue_create("队列名", DISPATCH_QUEUE ...
- GCD中使用dispatch_after函数延迟处理任务
在实际的开发中,经常会遇到想要在指定的时间间隔后执行某个处理 <一>在GCD中提供了dispatch_after函数来完成这一操作 dispatch_after(dispatch_time ...
- spring中的BeanFactory与ApplicationContext的作用和区别?
BeanFactory类关系继承图 1. BeanFactory类结构体系: BeanFactory接口及其子类定义了Spring IoC容器体系结构,由于BeanFactory体系非常的庞大和复杂, ...
随机推荐
- (转)offsetof与container_of宏[总结]
1.前言 今天在看代码时,遇到offsetof和container_of两个宏,觉得很有意思,功能很强大.offsetof是用来判断结构体中成员的偏移位置,container_of宏用来根据成员的地址 ...
- LuaInterface简介
Lua是一种很好的扩展性语言,Lua解释器被设计成一个很容易嵌入到宿主程序的库.LuaInterface则用于实现Lua和CLR的混合编程. (一)Lua from the CLR 测试环境:在VS2 ...
- Linux - Shell脚本调试方法
Shell脚本调试选项 Shell本身提供一些调试方法选项: -n,读一遍脚本中的命令但不执行,用于检查脚本中的语法错误. -v,一边执行脚本,一边将执行过的脚本命令打印到标准输出. -x,提供跟踪执 ...
- IE下点击scrollbar会导致焦点移动到body
现象 IE这货果然与众不同,当光标焦点在input时,点击同页面内其他区域的scrollbar,会导致焦点移动到body,从而触发绑定在input上的blur事件,如果input中的值与之前不同,甚至 ...
- Android 学习笔记之如何实现简单相机功能
PS:看来算法和数据结构还是非常有用的,以后每天都练习两道算法题目...这次忘了对代码进行折叠了..导致篇幅过长... 学习内容: 1.Android如何实现相机功能... 2.如何实现音频的录制.. ...
- Qt Style Sheet实践(一):按钮及关联菜单
导读 正如web前端开发中CSS(Cascade Style Sheet)的作用一样,Qt开发中也可以使用修改版的QSS将逻辑业务和用户界面进行隔离.这样,美工设计人员和逻辑实现者可以各司其职而不受干 ...
- C#关键字
关键字 abstract as base bool break byte case catch char checked decimal default delegate continue doubl ...
- 重构第30天 尽快返回 (Return ASAP)
理解:把条件语句中复杂的判断用尽快返回来简化. 详解:如首先声明的是前面讲的”分解复杂判断“,简单的来说,当你的代码中有很深的嵌套条件时,花括号就会在代码中形成一个长长的箭头.我们经常在不同的代码中看 ...
- 重构第19天 提取工厂类(Extract Factory Class)
理解:本文中的“提取工厂类”是指如果要创建的对象很多,则代码会变的很复杂.一种很好的方法就是提取工厂类. 详解:一般来说我们需要在代码中设置一些对象,以便获得它们的状态,从而使用对象,所谓的设置通常来 ...
- easyui-treegrid节点选择
easyui-treegrid本身不能实现选中父节点子节点全选,必须通过另外的方法来实现,这里说下如何通过修改节点样式添加checkbox来实现级联选择效果 首先需要格式化节点的样式 formatte ...