GCD中线程阻塞

队列:
存放任务的地方,可以理解为存放一段一段要执行的代码。

线程:
执行任务的流程。执行完A,接着执行B,然后再执行C。

任务的执行过程

同步派发必然会导致当前线程被阻塞住,和队列无关。派发函数必须等待任务完成才能返回。

用同步函数往并发队列派发任务时:
任务会当前线程执行。

用同步函数往串行队列派发任务时:
只要调用派发函数时不是在同一串行队列中,就不会阻塞,任务会在当前线程一个一个串行执行,然后派发函数返回。

而异步派发函数比较神奇,不用等待任务完成就可直接返回,因此即使在串行队列中向同一队列异步派发任务,也不会造成死锁,因为派发函数直接就返回了,串行队列中靠后的任务就可以得以执行。至于并发队列,各个任务直接本来就是并发执行的,不存在谁等待谁完成的问题。


同步:
 dispatch_queue_t queue = dispatch_queue_create("thread", DISPATCH_QUEUE_CONCURRENT);
    dispatch_sync(queue, ^{
        NSLog(@"test1");
    });
    dispatch_sync(queue, ^{
        void(^bb)() = ^() {
            sleep(2);
            NSLog(@"延时");
        };
        bb();
        NSLog(@"test2");
    });
    dispatch_sync(queue, ^{
        NSLog(@"test3");
    });
    
    dispatch_barrier_sync(queue, ^{
        //此处耗时,同步因此可能造成卡顿情况
      
        for (NSInteger i = 0; i < 500000000; i++) {
            if (i == 500000)NSLog(@"point1");
            if (i == 600000)NSLog(@"point2");
            if (i == 700000)NSLog(@"point3");
        }
        NSLog(@"barrier");
    });
    NSLog(@"aaa");
    dispatch_sync(queue, ^{
        NSLog(@"test4");
    });
    NSLog(@"bbb");
    dispatch_sync(queue, ^{
        NSLog(@"test5");
    });
    dispatch_sync(queue, ^{
        NSLog(@"test6");
    });

控制台输出:

2018-01-24 10:57:09.654 GCDDemo[3914:3750273] test1
2018-01-24 10:57:11.654 GCDDemo[3914:3750273] 延时
2018-01-24 10:57:11.654 GCDDemo[3914:3750273] test2
2018-01-24 10:57:11.655 GCDDemo[3914:3750273] test3
2018-01-24 10:57:12.868 GCDDemo[3914:3750273] aaa
2018-01-24 10:57:12.868 GCDDemo[3914:3750273] test4
2018-01-24 10:57:12.868 GCDDemo[3914:3750273] bbb
2018-01-24 10:57:12.868 GCDDemo[3914:3750273] test5
2018-01-24 10:57:12.869 GCDDemo[3914:3750273] test6

根据打印时间可以看到是同步执行的,同步的好处是可控制性强,一定是执行完了才往下走,缺点就是如果某一个函数比较耗时的话(此处是手动延时2秒),就会阻塞该线程的执行。


接下来再看dispatch_barrier_syncdispatch_barrier_async
dispatch_barrier_syncdispatch_sync效果几乎一样,顺步执行。
打开上面注释掉的dispatch_barrier_sync,运行,打印结果如下。

2018-01-25 09:56:38.473 GCDDemo[1671:973161] test1
2018-01-25 09:56:40.474 GCDDemo[1671:973161] 延时
2018-01-25 09:56:40.474 GCDDemo[1671:973161] test2
2018-01-25 09:56:40.474 GCDDemo[1671:973161] test3
2018-01-25 09:56:40.476 GCDDemo[1671:973161] point1
2018-01-25 09:56:40.476 GCDDemo[1671:973161] point2
2018-01-25 09:56:40.476 GCDDemo[1671:973161] point3
2018-01-25 09:56:41.650 GCDDemo[1671:973161] barrier
2018-01-25 09:56:41.650 GCDDemo[1671:973161] aaa
2018-01-25 09:56:41.650 GCDDemo[1671:973161] test4
2018-01-25 09:56:41.650 GCDDemo[1671:973161] bbb
2018-01-25 09:56:41.650 GCDDemo[1671:973161] test5
2018-01-25 09:56:41.650 GCDDemo[1671:973161] test6

可以看到打印结果的顺序并没有发生变化。
如果把dispatch_barrier_sync换成dispatch_barrier_async呢?打印结果如下:

2018-01-25 10:22:58.407 GCDDemo[1719:1045532] test1
2018-01-25 10:23:00.408 GCDDemo[1719:1045532] 延时
2018-01-25 10:23:00.408 GCDDemo[1719:1045532] test2
2018-01-25 10:23:00.408 GCDDemo[1719:1045532] test3
2018-01-25 10:23:00.408 GCDDemo[1719:1045532] aaa
2018-01-25 10:23:00.410 GCDDemo[1719:1045691] point1
2018-01-25 10:23:00.410 GCDDemo[1719:1045691] point2
2018-01-25 10:23:00.410 GCDDemo[1719:1045691] point3
2018-01-25 10:23:01.597 GCDDemo[1719:1045691] barrier
2018-01-25 10:23:01.597 GCDDemo[1719:1045532] test4
2018-01-25 10:23:01.598 GCDDemo[1719:1045532] bbb
2018-01-25 10:23:01.598 GCDDemo[1719:1045532] test5
2018-01-25 10:23:01.598 GCDDemo[1719:1045532] test6

可以看出,程序执行到dispatch_barrier_async的时候,没有等待结果返回,直接往下执行,直到遇到dispatch_sync,才会等待dispatch_barrier_async返回结果,再次继续往下执行。



    /**
     异步进程
     test1,2,3,不阻塞线程,并不确定哪个会先执行完.
     
     */
    dispatch_queue_t queue = dispatch_queue_create("thread", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"test1");
    });
    dispatch_async(queue, ^{
        sleep(2);
        NSLog(@"延时");
        NSLog(@"test2");
    });
    dispatch_async(queue, ^{
        NSLog(@"test3");
    });
    
//    dispatch_barrier_async(queue, ^{
//        for (NSInteger i = 0; i < 500000000; i++) {
//            if (i == 500000)NSLog(@"point1");
//            if (i == 600000)NSLog(@"point2");
//            if (i == 700000)NSLog(@"point3");
//        }
//        NSLog(@"barrier");
//    });
    NSLog(@"aaa");
    dispatch_async(queue, ^{
        NSLog(@"test4");
    });
    NSLog(@"bbb");
    dispatch_async(queue, ^{
        NSLog(@"test5");
    });
    dispatch_async(queue, ^{
        NSLog(@"test6");
    });
    
    return;
    dispatch_sync(queue, ^{
        NSLog(@"1");
    });
    dispatch_sync(queue, ^{
        NSLog(@"2");
    });
    dispatch_sync(queue, ^{
        NSLog(@"3");
    });
    dispatch_sync(queue, ^{
        NSLog(@"4");
    });
2018-01-24 11:11:29.320 GCDDemo[4002:3827389] aaa
2018-01-24 11:11:29.320 GCDDemo[4002:3832535] test1
2018-01-24 11:11:29.320 GCDDemo[4002:3837535] test3
2018-01-24 11:11:29.320 GCDDemo[4002:3827389] bbb
2018-01-24 11:11:29.320 GCDDemo[4002:3837536] test4
2018-01-24 11:11:29.321 GCDDemo[4002:3837535] test5
2018-01-24 11:11:29.321 GCDDemo[4002:3832535] test6
2018-01-24 11:11:31.324 GCDDemo[4002:3837525] 延时
2018-01-24 11:11:31.324 GCDDemo[4002:3837525] test2

可以看到异步的时候,每一个进程执行相互是不影响的。这种模式比较常见的就是网络解析图片的时候,异步解析,主线程加载图片。不阻塞线程,但是还有一个问题就是,程序可控性较差,有时候可能得不到结果。比如C要获得到A的结果才能正常执行,但是A还没有执行完毕的时候,C可能就执行了。

  1. 再来看dispatch_barrier_async,打开上面的注释,看一下打印结果:
2018-01-25 10:44:03.021 GCDDemo[1767:1097902] aaa
2018-01-25 10:44:03.021 GCDDemo[1767:1100068] test1
2018-01-25 10:44:03.021 GCDDemo[1767:1100069] test3
2018-01-25 10:44:03.021 GCDDemo[1767:1097902] bbb
2018-01-25 10:44:05.024 GCDDemo[1767:1098660] 延时
2018-01-25 10:44:05.024 GCDDemo[1767:1098660] test2
2018-01-25 10:44:05.026 GCDDemo[1767:1098660] point1
2018-01-25 10:44:05.026 GCDDemo[1767:1098660] point2
2018-01-25 10:44:05.026 GCDDemo[1767:1098660] point3
2018-01-25 10:44:06.300 GCDDemo[1767:1098660] barrier
2018-01-25 10:44:06.300 GCDDemo[1767:1100069] test4
2018-01-25 10:44:06.300 GCDDemo[1767:1100068] test5
2018-01-25 10:44:06.300 GCDDemo[1767:1100068] test6

可以看出代码执行不受影响,不用等待其他代码执行完成,各走各的。

  1. 换成dispatch_barrier_sync,再看一下打印结果
2018-01-25 14:57:29.253 GCDDemo[2189:1798062] test1
2018-01-25 14:57:29.254 GCDDemo[2189:1798689] 延时
2018-01-25 14:57:29.254 GCDDemo[2189:1798063] test3
2018-01-25 14:57:29.254 GCDDemo[2189:1798689] test2
2018-01-25 14:57:29.255 GCDDemo[2189:1796600] point1
2018-01-25 14:57:29.256 GCDDemo[2189:1796600] point2
2018-01-25 14:57:29.256 GCDDemo[2189:1796600] point3
2018-01-25 14:57:30.419 GCDDemo[2189:1796600] barrier
2018-01-25 14:57:30.420 GCDDemo[2189:1796600] aaa
2018-01-25 14:57:30.420 GCDDemo[2189:1796600] bbb
2018-01-25 14:57:30.420 GCDDemo[2189:1798689] test4
2018-01-25 14:57:30.420 GCDDemo[2189:1798689] test5
2018-01-25 14:57:30.420 GCDDemo[2189:1798063] test6

可以看出,在插入位置前面的代码,不受影响,各走各的,但是插入位置之后的,就必须等待dispatch_barrier_sync中的代码执行完毕才能执行。


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

推荐阅读更多精彩内容