iOS 趣谈信号量dispatch_semaphore_t

信号量的作用是用来控制资源/任务的并发量。这个怎么理解呢?

举个栗子:

体育课期中考试需要考核同一年级某个班的同学的体能是否达标,学校决定采用跑步并计算所用平均时间的方式,为了增加趣味及加强同学之间的凝聚力,体育老师们一致决定采用接力跑的方式,每个班级有3个接力棒,绕着足球场跑完一圈才可以交接棒,直到所有同学跑完为止。

那么我们可以想象一下是这样的一个场景:某班有47位同学,一开始因为只有三个接力棒,所以只能有三个同学站在起跑线,等发号枪响,三个同学就开始起跑,这里面有同学反应快会起跑得好一些,有同学经常锻炼可能会更快跑完一圈然后交棒,也就是过程的多样性问题,也比较贴合我们的编程的场景。

但是,在接力棒回来之前,剩下的44位同学只能在起跑点原地等待,直到正在进行跑步的同学回来并交接下一位同学才能起跑,按照这样的规则直到47位同学跑完即考核结束。

后话:计算47位同学跑一圈所用的平均时间即为某班的体能考核结果并全年级排名!

先看api:

dispatch_semaphore_create(long value)                                                                              --- ①
dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout)      --- ②
dispatch_semaphore_signal(dispatch_semaphore_t dsema)                                             --- ③

这里对上面的api以及结合之前的栗子做一个说明:

所传参数 value 理解为一个班级的一次考试有多少个接力棒,也可以理解为我们编程时能够分配的资源的数量

所传参数dsema 也就是上面创建的信号量,timeout 理解为等待前面运行的任务执行多长时间为止,上面跑步的例子是,现实场景是要一直等前面的同学回来才能继续跑,而不是比如等10s没有同学回来就可以继续跑,没有交接棒我们是不能跑的,那么我们这里的取值应该是:DISPATCH_TIME_FOREVER,现实意义就是拿走一根接力棒,能够继续拿接力棒跑的名额少掉一个,当没有交接棒是空闲时所有同学都要等待前面至少一位同学跑完。

所传参数dsema同理 也就是上面创建的信号量,这里的意义就是跑完一位同学,释放出一个接力棒,其他同学就有了接力棒可以拿着接力棒继续跑。

需要注意的是:信号总数是应该先减后加的,也就是先dispatch_semaphore_wait,后dispatch_semaphore_signal

demo:

dispatch_semaphore_t semaphore = dispatch_semaphore_create(3);
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    for (int i = 1; i <= 47; i++)
    {
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        NSLog(@"学号为%d的同学开始跑",i);
        dispatch_async(queue, ^{
            int time = arc4random() % 5;
            sleep(time);
            NSLog(@"学号为%d同学跑完,用时:%d秒",i ,time);
            dispatch_semaphore_signal(semaphore);
        });
    }

留意一下控制台里面输出的内容可以发现:同一时刻最多有三位同学在跑步,也就是有三个任务在执行,跑完一位同学才能有另一位同学继续跑,直到47位同学都跑完位置。

output:

20xx-xx-xx 17:09:50.727 CZB[74203:9934779] 学号为1的同学开始跑
20xx-xx-xx 17:09:50.727 CZB[74203:9934779] 学号为2的同学开始跑
20xx-xx-xx 17:09:50.727 CZB[74203:9934779] 学号为3的同学开始跑
20xx-xx-xx 17:09:51.731 CZB[74203:9934870] 学号为3同学跑完,用时:1秒
20xx-xx-xx 17:09:51.732 CZB[74203:9934779] 学号为4的同学开始跑
20xx-xx-xx 17:09:53.731 CZB[74203:9934869] 学号为2同学跑完,用时:3秒
20xx-xx-xx 17:09:53.731 CZB[74203:9934779] 学号为5的同学开始跑
20xx-xx-xx 17:09:53.734 CZB[74203:9934870] 学号为4同学跑完,用时:2秒
20xx-xx-xx 17:09:53.734 CZB[74203:9934779] 学号为6的同学开始跑
20xx-xx-xx 17:09:53.735 CZB[74203:9934870] 学号为6同学跑完,用时:0秒
20xx-xx-xx 17:09:53.735 CZB[74203:9934779] 学号为7的同学开始跑
20xx-xx-xx 17:09:54.731 CZB[74203:9934861] 学号为1同学跑完,用时:4秒
20xx-xx-xx 17:09:54.732 CZB[74203:9934779] 学号为8的同学开始跑
20xx-xx-xx 17:09:55.740 CZB[74203:9934870] 学号为7同学跑完,用时:2秒
20xx-xx-xx 17:09:55.740 CZB[74203:9934779] 学号为9的同学开始跑
20xx-xx-xx 17:09:57.736 CZB[74203:9934869] 学号为5同学跑完,用时:4秒
20xx-xx-xx 17:09:57.736 CZB[74203:9934779] 学号为10的同学开始跑
20xx-xx-xx 17:09:57.738 CZB[74203:9934861] 学号为8同学跑完,用时:3秒
20xx-xx-xx 17:09:57.739 CZB[74203:9934779] 学号为11的同学开始跑
20xx-xx-xx 17:09:57.739 CZB[74203:9934861] 学号为11同学跑完,用时:0秒
20xx-xx-xx 17:09:57.740 CZB[74203:9934779] 学号为12的同学开始跑
20xx-xx-xx 17:09:58.743 CZB[74203:9934861] 学号为12同学跑完,用时:1秒
20xx-xx-xx 17:09:58.743 CZB[74203:9934870] 学号为9同学跑完,用时:3秒
20xx-xx-xx 17:09:58.743 CZB[74203:9934779] 学号为13的同学开始跑
20xx-xx-xx 17:09:58.744 CZB[74203:9934779] 学号为14的同学开始跑
20xx-xx-xx 17:09:58.744 CZB[74203:9934870] 学号为13同学跑完,用时:0秒
20xx-xx-xx 17:09:58.744 CZB[74203:9934779] 学号为15的同学开始跑
20xx-xx-xx 17:10:00.748 CZB[74203:9934870] 学号为15同学跑完,用时:2秒
20xx-xx-xx 17:10:00.749 CZB[74203:9934779] 学号为16的同学开始跑
20xx-xx-xx 17:10:01.741 CZB[74203:9934869] 学号为10同学跑完,用时:4秒
20xx-xx-xx 17:10:01.742 CZB[74203:9934779] 学号为17的同学开始跑
20xx-xx-xx 17:10:01.747 CZB[74203:9934861] 学号为14同学跑完,用时:3秒
20xx-xx-xx 17:10:01.748 CZB[74203:9934779] 学号为18的同学开始跑
20xx-xx-xx 17:10:01.748 CZB[74203:9934861] 学号为18同学跑完,用时:0秒
20xx-xx-xx 17:10:01.748 CZB[74203:9934779] 学号为19的同学开始跑
20xx-xx-xx 17:10:04.743 CZB[74203:9934869] 学号为17同学跑完,用时:3秒
20xx-xx-xx 17:10:04.743 CZB[74203:9934779] 学号为20的同学开始跑
20xx-xx-xx 17:10:04.753 CZB[74203:9934870] 学号为16同学跑完,用时:4秒
20xx-xx-xx 17:10:04.754 CZB[74203:9934779] 学号为21的同学开始跑
20xx-xx-xx 17:10:05.752 CZB[74203:9934861] 学号为19同学跑完,用时:4秒
20xx-xx-xx 17:10:05.752 CZB[74203:9934779] 学号为22的同学开始跑
20xx-xx-xx 17:10:07.744 CZB[74203:9934869] 学号为20同学跑完,用时:3秒
20xx-xx-xx 17:10:07.744 CZB[74203:9934779] 学号为23的同学开始跑
20xx-xx-xx 17:10:07.755 CZB[74203:9934861] 学号为22同学跑完,用时:2秒
20xx-xx-xx 17:10:07.755 CZB[74203:9934870] 学号为21同学跑完,用时:3秒
20xx-xx-xx 17:10:07.756 CZB[74203:9934779] 学号为24的同学开始跑
20xx-xx-xx 17:10:07.756 CZB[74203:9934779] 学号为25的同学开始跑
20xx-xx-xx 17:10:09.756 CZB[74203:9934861] 学号为25同学跑完,用时:2秒
20xx-xx-xx 17:10:09.757 CZB[74203:9934779] 学号为26的同学开始跑
20xx-xx-xx 17:10:09.757 CZB[74203:9934861] 学号为26同学跑完,用时:0秒
20xx-xx-xx 17:10:09.757 CZB[74203:9934779] 学号为27的同学开始跑
20xx-xx-xx 17:10:09.758 CZB[74203:9934861] 学号为27同学跑完,用时:0秒
20xx-xx-xx 17:10:09.758 CZB[74203:9934779] 学号为28的同学开始跑
20xx-xx-xx 17:10:10.748 CZB[74203:9934869] 学号为23同学跑完,用时:3秒
20xx-xx-xx 17:10:10.748 CZB[74203:9934779] 学号为29的同学开始跑
20xx-xx-xx 17:10:11.751 CZB[74203:9934869] 学号为29同学跑完,用时:1秒
20xx-xx-xx 17:10:11.751 CZB[74203:9934779] 学号为30的同学开始跑
20xx-xx-xx 17:10:11.752 CZB[74203:9934869] 学号为30同学跑完,用时:0秒
20xx-xx-xx 17:10:11.752 CZB[74203:9934779] 学号为31的同学开始跑
20xx-xx-xx 17:10:11.761 CZB[74203:9934870] 学号为24同学跑完,用时:4秒
20xx-xx-xx 17:10:11.761 CZB[74203:9934779] 学号为32的同学开始跑
20xx-xx-xx 17:10:12.761 CZB[74203:9934861] 学号为28同学跑完,用时:3秒
20xx-xx-xx 17:10:12.761 CZB[74203:9934779] 学号为33的同学开始跑
20xx-xx-xx 17:10:12.764 CZB[74203:9934870] 学号为32同学跑完,用时:1秒
20xx-xx-xx 17:10:12.764 CZB[74203:9934779] 学号为34的同学开始跑
20xx-xx-xx 17:10:12.765 CZB[74203:9934870] 学号为34同学跑完,用时:0秒
20xx-xx-xx 17:10:12.765 CZB[74203:9934779] 学号为35的同学开始跑
20xx-xx-xx 17:10:15.755 CZB[74203:9934869] 学号为31同学跑完,用时:4秒
20xx-xx-xx 17:10:15.755 CZB[74203:9934779] 学号为36的同学开始跑
20xx-xx-xx 17:10:15.755 CZB[74203:9934869] 学号为36同学跑完,用时:0秒
20xx-xx-xx 17:10:15.756 CZB[74203:9934779] 学号为37的同学开始跑
20xx-xx-xx 17:10:15.766 CZB[74203:9934870] 学号为35同学跑完,用时:3秒
20xx-xx-xx 17:10:15.767 CZB[74203:9934779] 学号为38的同学开始跑
20xx-xx-xx 17:10:16.765 CZB[74203:9934861] 学号为33同学跑完,用时:4秒
20xx-xx-xx 17:10:16.765 CZB[74203:9934779] 学号为39的同学开始跑
20xx-xx-xx 17:10:17.760 CZB[74203:9934869] 学号为37同学跑完,用时:2秒
20xx-xx-xx 17:10:17.760 CZB[74203:9934779] 学号为40的同学开始跑
20xx-xx-xx 17:10:17.760 CZB[74203:9934869] 学号为40同学跑完,用时:0秒
20xx-xx-xx 17:10:17.761 CZB[74203:9934779] 学号为41的同学开始跑
20xx-xx-xx 17:10:17.767 CZB[74203:9934861] 学号为39同学跑完,用时:1秒
20xx-xx-xx 17:10:17.768 CZB[74203:9934779] 学号为42的同学开始跑
20xx-xx-xx 17:10:17.768 CZB[74203:9934861] 学号为42同学跑完,用时:0秒
20xx-xx-xx 17:10:17.768 CZB[74203:9934779] 学号为43的同学开始跑
20xx-xx-xx 17:10:18.774 CZB[74203:9934861] 学号为43同学跑完,用时:1秒
20xx-xx-xx 17:10:18.775 CZB[74203:9934779] 学号为44的同学开始跑
20xx-xx-xx 17:10:19.772 CZB[74203:9934870] 学号为38同学跑完,用时:4秒
20xx-xx-xx 17:10:19.772 CZB[74203:9934779] 学号为45的同学开始跑
20xx-xx-xx 17:10:19.772 CZB[74203:9934870] 学号为45同学跑完,用时:0秒
20xx-xx-xx 17:10:19.773 CZB[74203:9934779] 学号为46的同学开始跑
20xx-xx-xx 17:10:21.764 CZB[74203:9934869] 学号为41同学跑完,用时:4秒
20xx-xx-xx 17:10:21.764 CZB[74203:9934779] 学号为47的同学开始跑
20xx-xx-xx 17:10:22.773 CZB[74203:9934870] 学号为46同学跑完,用时:3秒
20xx-xx-xx 17:10:22.779 CZB[74203:9934861] 学号为44同学跑完,用时:4秒
20xx-xx-xx 17:10:23.769 CZB[74203:9934869] 学号为47同学跑完,用时:2秒

还有一个情况,如果想要提前结束考核,也就是结束任务那怎么办,我们回过头来再看一下dispatch_semaphore_create(long value)dispatch_semaphore_wait () 。每执行一次dispatch_semaphore_wait () 对应的信号总量的值: value值就会减一,当信用总量的值小于0时,将会结束所有的任务。

我们改一下代码:

dispatch_semaphore_t semaphore = dispatch_semaphore_create(3);
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    for (int i = 1; i <= 47; i++)
    {
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        
        if (i == 7) {
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        }
        
        NSLog(@"学号为%d的同学开始跑",i);
        
        dispatch_async(queue, ^{
            int time = arc4random() % 5;
            sleep(time);
            NSLog(@"学号为%d同学跑完,用时:%d秒",i ,time);
            dispatch_semaphore_signal(semaphore);
        });
    }

i == 7时,我们调用 dispatch_semaphore_wait () 4次,每调用一次信号量减1,由于我们总共只有3个信号量,所以会导致任务执行结束。

控制台输出结果是:

2017-10-31 17:38:01.228 CZB[74583:10003955] 学号为1的同学开始跑
2017-10-31 17:38:01.228 CZB[74583:10003955] 学号为2的同学开始跑
2017-10-31 17:38:01.228 CZB[74583:10003955] 学号为3的同学开始跑
2017-10-31 17:38:02.228 CZB[74583:10004053] 学号为1同学跑完,用时:1秒
2017-10-31 17:38:02.229 CZB[74583:10003955] 学号为4的同学开始跑
2017-10-31 17:38:02.230 CZB[74583:10004053] 学号为4同学跑完,用时:0秒
2017-10-31 17:38:02.230 CZB[74583:10003955] 学号为5的同学开始跑
2017-10-31 17:38:03.231 CZB[74583:10004053] 学号为5同学跑完,用时:1秒
2017-10-31 17:38:03.231 CZB[74583:10004045] 学号为3同学跑完,用时:2秒
2017-10-31 17:38:03.232 CZB[74583:10003955] 学号为6的同学开始跑
2017-10-31 17:38:03.232 CZB[74583:10004045] 学号为6同学跑完,用时:0秒
2017-10-31 17:38:04.228 CZB[74583:10004052] 学号为2同学跑完,用时:3秒

因此,如果想要提前结束任务可以根据具体情况执行 dispatch_semaphore_wait ()来中断任务队列。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容