GCD高级用法-信号量
2015-05-22 11:25
543 查看
GCD中的信号量是指 Dispatch Semaphore。
所谓信号,类似于道路上的信号灯,一种用来标识等待还是通过的标志。绿灯通过,红灯等待。道路中通过信号灯的颜色标识通过和等待,而Dispatch Semaphore中通过“计数”来标识通过和等待。
GCD的Dispatch Semaphore提供了三个函数操作Semaphore:
接下来详细说明一下这3个函数:
如果此时semaphore信号量的值
>= 1时:对semaphore计数进行减1,然后dispatch_semaphore_wait 函数返回。该函数所处线程就继续执行下面的语句。
如果此时semaphore信号量的值
= 0时:那么就阻塞该函数所处的线程,阻塞时长为timeout指定的时间,如果阻塞时间内semaphore的值被dispatch_semaphore_signal函数加1了,该函数所处线程获得了信号量被唤醒。然后对semaphore计数进行减1并返回,继续向下执行。如果阻塞时间内没有获取到信号量唤醒线程或者信号量的值一直为0,那么就要等到指定的阻塞时间后,该函数所处线程才继续向下执行。
dispatch_semaphore_wait 函数返回值为long类型;
当返回值为0时:说明semaphore的值大于等于1,或者在timeout指定时间之内,该函数所处的线程被成功唤醒(比如通过dispatch_semaphore_signal将线程唤醒)。
当返回值不为0时:说明semaphore的值等于0,此时timeout指定时间内该函数所处的线程处于阻塞。
另外,dispatch_semaphore_wait 函数的返回值也dispatch_group_wait 函数相同,可以通过返回值可以进行分支处理。
当返回值为0时:表示当前并没有线程等待其处理的信号量,其处理的信号量的值加1即可。
当返回值不为0时:表示其当前有(一个或多个线程)等待其处理的信号量,并且该函数唤醒了一个“等待的线 程”(当线程有优先级时,唤醒优先级最高的线程;否则随机唤醒)。
通过下面案例,看看Dispatch Semaphore的几个函数在实际开发中的应用:
所谓信号,类似于道路上的信号灯,一种用来标识等待还是通过的标志。绿灯通过,红灯等待。道路中通过信号灯的颜色标识通过和等待,而Dispatch Semaphore中通过“计数”来标识通过和等待。
GCD的Dispatch Semaphore提供了三个函数操作Semaphore:
dispatch_semaphore_create //创建一个semaphore dispatch_semaphore_signal //发送一个信号 dispatch_semaphore_wait //等待信号 /* 通过dispatch_semaphore_create 函数创建一个Semaphore并初始化信号的总量。 通过dispatch_semaphore_signal 函数发送一个信号,让信号总量加1。 通过dispatch_semaphore_wait可以使总信号量减1,当信号总量为0时就会一直等待,否则就可以正常执行 */
接下来详细说明一下这3个函数:
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);通过dispatch_semaphore_create 函数生成Dispatch Semaphore。参数表示计数的初始值,上面设置的初始值为1。
long dispatch_semaphore_wait(dispatch_semaphore_t semaphore, dispatch_time_t timeout);
如果此时semaphore信号量的值
>= 1时:对semaphore计数进行减1,然后dispatch_semaphore_wait 函数返回。该函数所处线程就继续执行下面的语句。
如果此时semaphore信号量的值
= 0时:那么就阻塞该函数所处的线程,阻塞时长为timeout指定的时间,如果阻塞时间内semaphore的值被dispatch_semaphore_signal函数加1了,该函数所处线程获得了信号量被唤醒。然后对semaphore计数进行减1并返回,继续向下执行。如果阻塞时间内没有获取到信号量唤醒线程或者信号量的值一直为0,那么就要等到指定的阻塞时间后,该函数所处线程才继续向下执行。
dispatch_semaphore_wait 函数返回值为long类型;
当返回值为0时:说明semaphore的值大于等于1,或者在timeout指定时间之内,该函数所处的线程被成功唤醒(比如通过dispatch_semaphore_signal将线程唤醒)。
当返回值不为0时:说明semaphore的值等于0,此时timeout指定时间内该函数所处的线程处于阻塞。
另外,dispatch_semaphore_wait 函数的返回值也dispatch_group_wait 函数相同,可以通过返回值可以进行分支处理。
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1); long result = dispatch_semaphore_wait(semaphore, 1ull * NSEC_PER_SEC); if (result == 0) { /* 返回0时,可安全地执行需要进行排他控制的处理。该处理结束后通过dispatch_semaphore_signal 函数将Dispatch Semaphore 的计数值加1. */ }else{ /* 说明semaphore的值等于0,此时timeout指定时间内该函数所处的线程处于阻塞 */ }
long dispatch_semaphore_signal(dispatch_semaphore_t dsema);
当返回值为0时:表示当前并没有线程等待其处理的信号量,其处理的信号量的值加1即可。
当返回值不为0时:表示其当前有(一个或多个线程)等待其处理的信号量,并且该函数唤醒了一个“等待的线 程”(当线程有优先级时,唤醒优先级最高的线程;否则随机唤醒)。
通过下面案例,看看Dispatch Semaphore的几个函数在实际开发中的应用:
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_semaphore_t semaphore = dispatch_semaphore_create(1); NSMutableArray *array = [[NSMutableArray alloc]init]; for (NSInteger i = 0; i < 100000; i++) { dispatch_async(queue, ^{ /* 此时semaphore信号量的值如果 >= 1时:对semaphore计数进行减1,然后dispatch_semaphore_wait 函数返回。该函数所处线程就继续执行下面的语句。 此时semaphore信号量的值如果=0:那么就阻塞该函数所处的线程,阻塞时长为timeout指定的时间,如果阻塞时间内semaphore的值被dispatch_semaphore_signal函数加1了,该函数所处线程获得了信号量被唤醒。然后对semaphore计数进行减1并返回,继续向下执行。 如果阻塞时间内没有获取到信号量唤醒线程或者信号量的值一直为0,那么就要等到指定的阻塞时间后,该函数所处线程才继续向下执行。 执行到这里semaphore的值总是1 */ dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); /* 因为dispatch_semaphore_create创建的semaphore的初始值为1,执行完上面的 dispatch_semaphore_wait函数之后,semaphore计数值减1会变为0,所以可访问array对象的线程只有1个,因此可安全地对array进行操作。 */ [array addObject:[NSNumber numberWithInteger:i]]; /* 对array操作之后,通过dispatch_semaphore_signal将semaphore的计数值加1,此时semaphore的值由变成了1,所处 */ dispatch_semaphore_signal(semaphore); }); } }
相关文章推荐
- GCD高级用法:分派源与信号量 7个 Demo
- GCD高级用法(一):dispatch_after
- iOS 多线程 GCD(滚床单) 的高级用法
- GCD 高级用法(一) dispatch after
- Swift3 GCD的基本用法(一) - 任务和队列、服务优先级、信号量
- GCD高级用法-Dispatch I/O
- iOS 线程之GCD的高级用法
- GCD高级用法(二) dispatch_group
- swift详解之十七-----------GCD的一些高级用法
- Parse源码浅析系列(一)---Parse的底层多线程处理思路:GCD高级用法
- GCD高级用法(三) 多线程单例
- Selenium用户指南 - 第五章 WebDriver: 高级用法
- VIM 高级用法(一)
- Java中for循环的高级用法
- Android属性动画完全解析(中),ValueAnimator和ObjectAnimator的高级用法
- TileMap高级用法
- input高级限制级用法
- iOS开发多线程篇—GCD的常见用法
- MongoDB基本用法(增删改高级查询)
- jQuery动画高级用法(上)——详解animation中的.queue()函数