GCD中的dispatch_semaphore的语法与作用

(一)引入问题

当并行执行的处理更新数据时,会产生数据不一致的情况,有时应用程序还会异常结束,虽然使用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 }

 

posted @ 2016-02-27 16:33  iOS-Denzel  阅读(946)  评论(0编辑  收藏  举报