从死锁角度窥探GCD

       最近一直没有更新简书是因为在开发和测试阶段,有任务,没有进行学习,不过在做任务的时候也遇到了一些技术点,在这里总结一下。

       今天我们来深度学习GCD。深度学习我们可以理解为进阶学习,该文试图用demo里面的栗子形象学习GCD的用法。

      其实在我们平时的开发过程中,这个GCD甚至多线程用的并不多,就像算法,我们在开发过程中用的并不多,但是这些知识确实是考验我们基础是否扎实的一个标准,还是之前说过的:java和OC或者别的语言,只是语言形式不同罢了,实际运用的计算机思想是通用的。所以我们通过学习GCD,可以以此为突破口,进而熟知多线程相关的知识。“管中窥豹,可见一斑”:比喻从观察到的部分,可以推测全貌。类似的我们举一反三:“冰山一角,可见冰山”,哈哈哈。。。

     1、死锁

    昨天看到一个面试题,题目如下:

        通过上边的解释我们可以看出,主线程中同步插入一个主线程的队列,会造成主线程等着插入的线程完成后才会进行,而要插入的线程完成,那么主线程必须完成,这样就形成了,你中有我我中有你互相引用的问题,就好像循环引用似的,互相牵制,结果大事未了,含恨而终。。。

        那么我们如果插入的线程不是主线程呢,我们试试看。

       这里我在打印4之后,给主线程插入一个同步队列queue1,这样的话,主线程会被阻塞,等待dispath_sync的block执行完成后再继续执行,打印出5来了,然后主线程继续执行打印6。

我们再来看下边的这段代码:

结果在上图,只打印了4和5,我们分析这段代码:打印4,同步之行queue1队列,打印5,再同步执行queue1队列,我们知道dispath_sync是需要等待block里面的结果出来后再进行下边的执行步骤的,这里造成死锁:后边的queue1等待前边的queue1执行完成后才进行后边的步骤,但是前面的queue1也在等待后边的queue1执行完成,这样造成死锁。

由此我们可以得出:dispath_sync不能执行所在的线程的线程,不能执行所在队列中的队列,不然就会造成死锁。

我们再来看下边的代码:

这里我们更能理解async和sync的区别:


这里如果我不打断点,会一直打印4,而且我们看左上角那里会看到CPU消耗时99%,电量显示时high。

我们这时候来看一些概念性的知识:

2、什么是GCD、GCD的优势

(1)GCD全称是Grand Central Dispatch,可以为“伟大的中枢调度”。纯C语言,提供了非常多且强大的函数

(2)优势

GCD是苹果公司为多核的并行运算提出的解决方案

GCD会自动利用更多的CPU内核(比如双核、四核)

GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)

程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码

3、什么是任务和队列

GCD中有2个核心概念

(1)任务:执行什么操作

(2)队列:用来存放任务

GCD的使用就2个步骤(1)定制任务(2)确定想做的事情

将任务添加到队列中,GCD会自动将队列中的任务取出,放到对应的线程中执行

提示:任务的取出遵循队列的FIFO原则:先进先出,后进后出

4、执行任务

1)GCD中有2个用来执行任务的函数,即同步方式、异步方式执行任务

dispatch_sync(dispatch_queue_t queue,dispatch_block_t block);

dispatch_async(dispatch_queue_t queue,dispatch_block_t block);

block里面的东西,就是你准备交给队列queue处理的任务

2)同步、异步、串行、并发

同步和异步决定要不要开启新的线程

同步:在当前线程中执行任务,不具备开启新线程的能力

异步:在新的线程中执行任务,具备开启新线程的能力

串行和并行决定任务的执行方式

串行:一个任务执行完毕后,再执行下一个任务

并发:多个任务并发(同时)执行

5、怎么获取线程

1)创建队列方法

dispatch_queue_create(const char *label, dispatch_queue_attr_t attr)   //创建队列,在非ARC中要手动释放。这个方法既可以创建串行队列,也可以创建并发队列

注意:第一个参数是字符指针,表示队列名称,第二个是队列的属性(传NULL或DISPATCH_QUEUE_SERIAL都表示的是串行队列,传DISPATCH_QUEUE_CONCURRENT,表示并发队列)

dispatch_get_main_queue();   //使用它时,要注意死锁,因为不论是同步还是异步执行他,都不会开辟新的线程,他会在主队列执行

dispatch_get_global_queue(long identifier, unsigned long flags)   //并发队列,第一个参数是设置优先级的,后一个参数是为将来使用,可以传0

从上面可以看出:queue如果是串行队列,那么,会开辟一个新的线程,但是,是前一个执行完毕,再执行后一个。并发队列会开启两个线程,并发执行。

讨论:哪些会死锁?死锁的原因是什么?开辟了新线程么?

<1>同步执行同一个串行队列

<2>异步执行同一个串行队列

<3>同步异步执行同一个串行队列

<4>异步同步执行同一个串行队列

<5>异步执行不同串行队列

<6>同步执行主队列

<7>同步执行不同串行队列

<8>异步同步执行不同串行队列

<9>同步异步执行不同串行队列

<10>同步执行不同并发队列

<11>同步异步执行同一个并发队列

<12>异步同步执行同一个并发队列

<13>异步执行不同并发队列

<14>异步执行同一个/不同并发队列

6、总揽

1、图片总体看看GCD

延时方法举个栗子,看时间:

注: dispatch_after 函数并不是在指定时间后执行处理,而是在指定时间后追加处理到Dispatch Queue。例如Main Dispatch Queue在主线程的RunLoop中执行。所以在比如每隔1/60秒执行的RunLoop,Block最快在3秒后执行,最慢在 3+1/60秒后执行。所以上图中,performSelector和NSTimer的延时执行比我们设定的2秒和4秒分别晚了4毫秒和3毫秒,但是我们再看dispatchAfter的延时执行,晚了0.582秒,即582毫秒。

2. dispatch_barrier_async的作用是什么?(dispatch栅栏)

在并行队列中,为了保持某些任务的顺序,需要等待一些任务完成后才能继续进行,使用 barrier 来等待之前任务完成,避免数据竞争等问题。 dispatch_barrier_async 函数会等待追加到Concurrent Dispatch Queue并行队列中的操作全部执行完之后,然后再执行 dispatch_barrier_async 函数追加的处理,等 dispatch_barrier_async 追加的处理执行结束之后,Concurrent Dispatch Queue才恢复之前的动作继续执行。

打个比方:比如你们公司周末跟团旅游,高速休息站上,司机说:大家都去上厕所,速战速决,上完厕所就上高速。超大的公共厕所,大家同时去,程序猿很快就结束了,但程序媛就可能会慢一些,即使你第一个回来,司机也不会出发,司机要等待所有人都回来后,才能出发。 dispatch_barrier_async 函数追加的内容就如同 “上完厕所就上高速”这个动作。

举个栗子:猫8888是设置的栅栏

通过结果我们可以看到:猫8888之前的无序的,后边的也是无序的。在多个并行处理之间插入指定处理后再继续多个并行处理。

3、 Dispatch Group

如果想要在追加到多个Dispatch Queue中的多个处理全部结束后执行结束处理,可使用Dispatch Group。

例如:

举个栗子:

参考:GCD用法详细介绍

           招聘一个靠谱的iOS(下)



最后,哪里不对的地方可以给我留言,我会及时改进的,谢谢大家。

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

推荐阅读更多精彩内容