信号量与并发控制

栏目: IOS · 发布时间: 5年前

内容简介:我们知道在网络请求时,会用到大量的异步线程。但异步线程的开辟并不是没有代价的,在硬件资源有限的情况下,有时候就需要对这些异步线程做一些控制,防止线程过多造成资源浪费;或者线程之间存在依赖关系,一个线程的执行必须等另外一个线程完成,而信号量(semaphore)就是 GCD 中用来做并发控制(即同步)的一种机制。GCD 中的信号量包含了 3 个函数:例如:

我们知道在网络请求时,会用到大量的异步线程。但异步线程的开辟并不是没有代价的,在硬件资源有限的情况下,有时候就需要对这些异步线程做一些控制,防止线程过多造成资源浪费;或者线程之间存在依赖关系,一个线程的执行必须等另外一个线程完成,而信号量(semaphore)就是 GCD 中用来做并发控制(即同步)的一种机制。

GCD 中的信号量包含了 3 个函数:

  1. dispatch_semaphore_create(long):

    用于创建一个信号量,需要注意的是,这里long 参数必须大于或等于 0。

  2. dispatch_semaphore_signal(dispatch_semaphore_t) :

    这个函数会使传入的信号量加1;

  3. 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);
    
      });
    
  }
  1. 创建一个信号量,初始值为 2;
  2. 一个循环,循环 10 次,每次循环创建一个异步线程;
  3. 第一次循环中,首先 dispatch_semaphore_wait,信号量 -1 ,2-1=1,信号量大于 0,继续执行,
  4. 再创建一个线程。循环 2 次后创建两个线程,信号量为 0,dispatch_semaphore_wait 后面的语句不再执行,线程不再创建。
  5. 当其中一个异步线程执行完后,信号量 +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,第二个线程才会创建,同理类推。相当于同步执行了线程中的代码,但避免了嵌套代码块的写法(即金字塔地狱)。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数字麦克卢汉

数字麦克卢汉

(美)保罗﹒莱文森(Paul Levinson) / 何道宽 / 社会科学文献出版社 / 2001年 / 20.0

本书是一本三合一的书。既是麦克卢汉评传,又是一部专著,而且是让网民“扫盲”和提高的指南。 《数字麦克卢汉》实际上有两个平行的主题和任务。一个是批评和张扬麦克卢汉。另一个是写作者自己的思想。它“不仅谋求提供进入数字时代的向导……而且谋求证明麦克卢汉思想隐而不显的准确性。为了完成这个双重任务,本书的每一章都试图阐明麦克卢汉的一种重要的洞见、原则或概念。与此同时,它试图揭示麦克卢汉告诉我们一些什么......一起来看看 《数字麦克卢汉》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

SHA 加密
SHA 加密

SHA 加密工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具