iOS 多线程GCD主线程上同步执行主队列方法卡死的解释

我们都知道,在主线程上,同步执行,为主队列添加 task 会导致卡死。

到底该怎么理解呢?

第一 

主线程有一个特点:主线程会先执行主线程上的代码片段,然后才会去执行放在主队列中的任务。

第二

同步执行  dispatch_sync函数的特点:该函数只有在该函数中被添加到某队列的某方法执行完毕之后才会返回。即 方法会等待 task 执行完再返回


主线程执行为主队列添加任务

具体分析:

dispatch_sync 函数本身是放在主线程中执行的,也就是说他本身也是属于主线程执行任务的一部分。根据主线程的特点:主线程会等主线程上的代码执行完毕之后才会去执行放置到主队列中的 task;再根据 disptach_sync 函数特点, task 不执行完毕,dispatch_sync 函数不返回。这样,dispatch_sync 为了返回会等 task 执行完毕也就是主线程执行完,而 task 执行又等着主线程上的代码执行完,也即主线程上 dispatch_sync 代码执行完。

主队列中的任务必须按顺序挨个执行

任务要等主线程有空的时候(即主队列中的所有任务执行完)才能执行

主线程要执行完“结束标志”的任务后才有空

“任务”和“结束标志”两个任务互相等待,造成死锁

结果

卡死的原因已经说明清楚了。

现在来证明上面两点

第一:主线程执行特点,先执行主线程上的代码,再执行主队列中的任务。

-------划重点了!  这里强调~~~~~>  主队列 ! 主队列 ! 主队列 !

如果是串行队列,在主线程上同步方法添加一个任务到串行队列。


主线程上为串行队列添加任务


结果

不会死锁那说明,没有出现上面说的互相等待的问题,我们来分析一下。

首先,dispatch_sync 函数的特性没变,等待 task 执行完毕之后才能返回。

既然,程序能正常运行,那么必然 dispatch_sync 函数等到了 task 的返回。

从结果输出的顺序看出,  同步执行串行队列的实质为


所以在上面会强调主队列等待,普通串行队列不等待主线程代码的执行。

主线程会先执行完主线程上的代码,然后再执行主队列中的方法!!

我们怎么证明呢?要知道在主线程上同步为主队列添加 task 会死锁。

那么,我们在主线程上异步为主队列添加 task


task 被异步添加到主队列
结果

结果好像是按照我们预期那样执行的,先执行主线程上代码在执行主队列中 task。 

可是,仅仅这样就判定主线程会先执行主线程中代码再执行主队列中的 task 还不准确。 

首先,dispatch_async 函数的功能,我们都会想到,觉得是否开启新的线程去执行队列中的任务。其实还有一点,那就是这个函数本身不会阻塞线程的执行,不同于上述 dispatch_sync,dispatch_sync 会阻塞线程,知道里面的 task 执行完毕后才返回。这个特性在主线程乃至子线程都奏效。

所以,执行到dispatch_async函数时不等待 task 执行直接接着执行后面的代码。考虑到队列中 task 调用问题(这是需要 cpu 调度的,会消耗一定时间),我们在原代码基础之上,dispatch_async函数之后然线程 sleep 一会,看添加到主队列中的 task 是否真正在等待主线程上代码的执行。

继续验证


结果和刚才一样,证明异步执行的时候,主队列的 task 会等待主线程的代码执行
结果

那么我们就证明了,主线程确实会先执行完主线程上代码再执行主队列中的 task(因为 dispatch_async 不会等待函数中被添加到某队列的某方法执行完毕之后才会返回),  主队列又叫全局串行队列。

我们解决死锁的方法,通常是把死锁方法放到子线程里面执行。

为什么现在就不会死锁了呢?

子线程同步执行,一样阻塞, dispatch_async函数会阻塞下面 NSLog 方法进行输出,dispatch_async函数结束的时刻是里面 task 执行完毕的时刻,

dispatch_async将 task 放入主队列中,主队列等待主线程上代码执行完毕之后,再执行主队列中的 task ,主队列中的 task 执行完毕之后再跳出dispatch_async函数之后子线程最后的 NSLog 方法。

证明:


主线程代码进行 3s 的 sleep
结果和预期一样

接下来在子线程上把同步方法换成异步方法呢?

子线程不阻塞,接着执行,然后 sleep 3s ,执行主线程代码,最后是主队列task
结果

以后我们再见到dispatch_async 或者dispatch_sync时,除了要考虑他们是否会开启新的线程之外,还应该记住:

dispatch_async不阻塞当前线程

dispatch_sync阻塞当前线程

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

推荐阅读更多精彩内容

  • iOS多线程编程 基本知识 1. 进程(process) 进程是指在系统中正在运行的一个应用程序,就是一段程序的执...
    陵无山阅读 5,979评论 1 14
  • 本篇博客共分以下几个模块来介绍GCD的相关内容: 多线程相关概念 多线程编程技术的优缺点比较? GCD中的三种队列...
    有梦想的老伯伯阅读 1,008评论 0 4
  • 当你苏醒的那刻起,看到自己容颜大变,心中是否失落?手指拂过脸庞,是否陌生? 也许在决定要为赤焰军洗刷冤屈时,内...
    静谧夜空阅读 159评论 2 0
  • 1.玩贴纸书《我的第一本数学启蒙》,贴了十几页。 2.猜数字1-10,是小朋友主动提出要玩的,今天很有进步,比如我...
    宛宛妈咪阅读 81评论 0 0