关于死锁

基础知识

笔者对照阅读了苹果官方的开发者指南和一些博客,发现对于队列、死锁的理解很容易产生一些误区,笔者在下文中将一一祭献出这些理解误区(😈~)
从原理层面理解死锁产生的原因,比反复举例的方法更快,所以基础知识部分一定要看哦

队列 dispatch queue

队列是一个用于管理多个任务的数据结构,按照FIFO的顺序执行block。每个注册到队列的任务都会被分配到系统管理的线程池中执行。
常见误区:串行队列是单线程,并行队列是多线程
这个说法是错误的,不管是串行还是并行队列都会将任务分配给多个不同的线程执行,区别在于串行队列能够保证一次仅执行一个任务,而并行队列一次可执行多个任务

队列类型 描述
串行队列 私有队列,一次仅执行一个任务,任务所在的线程由队列管理;常用于顺序读写某一特殊数据资源
并行队列 全局队列,可同时执行多个任务,任务所在的线程由队列管理
主线程队列 全局的串行队列,负责在主线程中执行任务;该队列中的任务与应用runloop中的其它事件交错执行
常见方法
方法 描述
dispatch_queue_t <strong>dispatch_get_global_queue</strong>(long identifier, unsigned long flags); 返回一个全局并行队列,identifier确定队列优先级,取值为QOS_CLASS_USER_INTERACTIVE|QOS_CLASS_USER_INITIATED|QOS_CLASS_UTILITY|QOS_CLASS_BACKGROUND,flag暂不使用,设为0
dispatch_queue_t <strong>dispatch_queue_create</strong>(const char *label, dispatch_queue_attr_t attr) 创建一个队列,label是队列的唯一标识符,命名格式为com.example.myqueue;attr参数,DISPATCH_QUEUE_SERIAL表示创建串行队列,DISPATCH_QUEUE_CONCURRENT表示创建并行队列
dispatch_queue_t <strong>dispatch_get_main_queue</strong>(void) 返回主线程队列
dispatch_queue_t <strong>dispatch_get_current_queue</strong>(void) 返回当前队列
内存管理

所有的队列都是引用计数的数据类型,一个队列被创建后的初始引用计数为1;但是我们不须要管理全局并行队列,所有队列上retain、release操作都会被忽略;故而不须要存储全局队列的指针变量,每次使用时调用dispatch_get_global_queue方法来获取全局队列。

补充

1.相互独立的队列是并行执行的(这个说法不太准确,应该是相互独立的队列中的任务是可以并行执行的,没有关联关系)
2.系统决定某一时刻并行执行的任务总数量
3.系统决定执行哪个任务时会考虑队列的优先级
4.任务在添加到队列的那一刻即要做好执行的准备
5.私有队列是基于引用计数的对象,每个被加到队列的block都持有指向队列的指针,直到此block执行结束后销毁;故而所有block执行完毕后队列才有可能被系统回收。

dispatch_async&dispatch_sync

常见误区:async并行执行任务,sync串行执行任务
async、sync并不会执行某个任务,二者的差别也没有我们想象的那么大,都是把block添加到队列中,唯一的区别是sync会阻塞线程直到block执行完毕,而dispatch会马上返回。
可以看一下官网给出的定义:

方法 定义
dispatch_async Submits a block for asynchronous execution on a dispatch queue and returns immediately
dispatch_sync Submits a block object for execution on a dispatch queue and waits until that block completes

方法中的queue参数决定是串行还是并行执行block。

死锁的产生

这是一个最常见的死锁产生的场景:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        dispatch_sync(dispatch_get_main_queue(), ^(void){
            //block code
        });
    }
    return 0;
}

如果你将这段代码中dispatch_sync方法放到项目的Appdelegate方法中,会发现应用会卡在启动界面。

常见误区:在主线程中添加dispatch_sync,会导致死锁。
这个说法并不准确,官网给出了更加准确(geek)的说法:

Do not call the dispatch_sync function from a task that is executing on the same queue that you pass to your function call. Doing so will deadlock the queue. If you need to dispatch to the current queue, do so asynchronously using the dispatch_async function.

你不应该将block添加到调用它的dispatch_sync方法所在的队列上;以上dispatch方法在主线程队列中调用,同时又将block添加到了dispatch_get_main_queue()返回的主线程队列中,故而造成了死锁。
为什么会这样呢?如果你充分理解了前文中的预备知识,原因是可以推理出来的,这段代码导致了以下事件:
1.dispatch_sync将block添加到主线程队列
2.dispatch_sync阻塞主线程直到block执行完毕
3.线程被阻塞了,block永远无法执行

dispatch_sync多么尴尬,它阻碍了自己的block的执行!

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

推荐阅读更多精彩内容