内容简介:我们知道在网络请求时,会用到大量的异步线程。但异步线程的开辟并不是没有代价的,在硬件资源有限的情况下,有时候就需要对这些异步线程做一些控制,防止线程过多造成资源浪费;或者线程之间存在依赖关系,一个线程的执行必须等另外一个线程完成,而信号量(semaphore)就是 GCD 中用来做并发控制(即同步)的一种机制。GCD 中的信号量包含了 3 个函数:例如:
我们知道在网络请求时,会用到大量的异步线程。但异步线程的开辟并不是没有代价的,在硬件资源有限的情况下,有时候就需要对这些异步线程做一些控制,防止线程过多造成资源浪费;或者线程之间存在依赖关系,一个线程的执行必须等另外一个线程完成,而信号量(semaphore)就是 GCD 中用来做并发控制(即同步)的一种机制。
GCD 中的信号量包含了 3 个函数:
-
dispatch_semaphore_create(long):
用于创建一个信号量,需要注意的是,这里long 参数必须大于或等于 0。
-
dispatch_semaphore_signal(dispatch_semaphore_t) :
这个函数会使传入的信号量加1;
-
dispatch_semaphore_wait (dispatch_semaphore_t):
函数会使传入的信号量减1;如果信号量的值大于0,该函数所处线程就继续执行下面的语句,并且将信号量的值减1;如果信号量为0,那么这个函数就阻塞当前线程等待到超时时间或者一直等待(DISPATCH_TIME_FOREVER)。
例如:
// 1 dispatch_semaphore_t semaphore = dispatch_semaphore_create(2); // 2 for (int i= 0; i< 3; i++) { //3 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); // 4 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ sleep(2);// do something // 5 dispatch_semaphore_signal(semaphore); }); }
- 创建一个信号量,初始值为 2;
- 一个循环,循环 10 次,每次循环创建一个异步线程;
- 第一次循环中,首先 dispatch_semaphore_wait,信号量 -1 ,2-1=1,信号量大于 0,继续执行,
- 再创建一个线程。循环 2 次后创建两个线程,信号量为 0,dispatch_semaphore_wait 后面的语句不再执行,线程不再创建。
- 当其中一个异步线程执行完后,信号量 +1,dispatch_after 再次创建新的线程。
这里,信号量相当于起了一个节流阀的作用,我们创建信号量时就指定了异步线程最大数量为 2,到达最大线程数后线程就必须等待一段时间才能创建新线程。这里的 DISPATCH_TIME_FOREVER 表示一直等待。也可以指定为一个 dispatch_time_t 类型的时间。
再来看一个例子:
// 1 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); // 2 for (int i= 0; i< 3; i++) { //3 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); // 4 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ sleep(2);// do something // 5 dispatch_semaphore_signal(semaphore); }); }
这里的代码跟前面一模一样,除了我们将信号量设置为 0。这样循环在第一次执行时就会停住了,因为 dispatch_semaphore_wait 在信号量为 0 时会无限等待。要让循环能够进行,可以将dispatch_semaphore_wait 放到最后:
// 1 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); // 2 for (int i= 0; i< 3; i++) { // 3 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ sleep(2);// do something // 4 dispatch_semaphore_signal(semaphore); }); // 5 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); }
这样,第一次循环时首先创建一个线程,然后检查信号量为 0,等待,等第一个线程执行完,信号量+1,第二个线程才会创建,同理类推。相当于同步执行了线程中的代码,但避免了嵌套代码块的写法(即金字塔地狱)。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Java 并发编程那些事儿(五):闭锁、栅栏、信号量
- Java并发编程的艺术(十一)——倒计时器、同步屏障、信号量
- 树莓派基础-模拟信号和数字信号的区别
- xenomai内核解析之信号signal(二)---xenomai信号处理机制
- 没信号也可救你命:苹果新专利让iPhone无信号也可充当紧急信标
- 信号量
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
HTML Dog
Patrick Griffiths / New Riders Press / 2006-11-22 / USD 49.99
For readers who want to design Web pages that load quickly, are easy to update, accessible to all, work on all browsers and can be quickly adapted to different media, this comprehensive guide represen......一起来看看 《HTML Dog》 这本书的介绍吧!