热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

死锁GCD多线程Ios

Ios中GCD死锁困扰很多人,分享一点个人经验,希望可以帮助到更多人.文章有点长,首先第一张图是正确的代码,交代一下基本流程和原理,第二张图是一个最简单的死锁后面是原理分析,第三张

IosGCD死锁困扰很多人,分享一点个人经验,希望可以帮助到更多人.文章有点长,首先第一张图是正确的代码,交代一下基本流程和原理,第二张图是一个最简单的死锁后面是原理分析,第三张图稍加了一点点难度的死锁,后面是原理分析,第四章是正确的代码,后面是原理分析

我在后面又补充了一篇文章来说死锁.<死锁补充>

.首先来看这段 正确的  代码:

touchesbegan中调用test方法,可以看到如下打印

 分析一下原理:

1>调用test方法执,行到25行时没有开启线程,在主线程中打印

2> 执行到31行时检测到异步函数async,此时async函数直接返回,不会等函数中的block1执行完毕就返回,执行到31行系统有两件事要做,第一跳至42行打印,第二开启一个新的线程1(是子线程而非主线程)执行block1当中的内容.所以看到主线程0,4先打印,打印结束就没有主线程的事情了,接下来子线程登场.()

3> 子线程1执行block1的内容:

     3.1执行33行打印    (子线程1)  打印

     3.2执行到35行检测到async异步函数,直接返回,不等待block2执行完毕,程序继续向下执行,即打印39 3 子线程打印,同时又创建一个  (子线程2)

4> ok  到这里我们还需要分析一下,程序运行到这里我们一共经历了几个线程?三个!主线程一个,31 35行分别创建了两个子线程12

(怎么看是否创建了新的线程?"一般"来说看函数,async异步执行还是sync同步执行,为什么要用"一般"?往下看)

     那么问题来了1>   33行和 39行的打印(1,3打印)都在一个线程上我们可以理解(看线程地址),但是为什么36行的打印 也和这两个            同一个线程呢?  因为31行创建了一个子线程 打印了33行和39行之后,这个线程的任务结束了,正常来说就要销毁了,没他什么事了.但是我们在35行又需要创建一个线程,创建线程需要时间和空间成本(占用内存)所以在子线程1执行完任务进入线程池要销毁的时候,发现系统还要再创建一个线程,ok那我就不销毁了,你也不用再创建了,所以线程1就被重复利用了,所以他们在一个线程上打印.关于为什么在同一个子线程上打印,我给出的只是一个理解的方式,是不是准确的?我不确定.因为线程很多的情况十分复杂,我们这个事例程序很简单,可以这样理解.所以我前面说的是有问题的,这个程序只经历了两个线程,主线程和同一个子线程

5>ok我们回来  在子线程1执行33  39行的打印之后,被系统重复利用,来执行35block的内容,36行打印结束一个消息循环结束,进入休眠等待下次触摸屏幕.

6>总结:为什么程序的打印结果会是这样的?与两个因素有关1>函数  async异步执行还是sync同步执行2>队列我们创建的是串行队列这个串行队列里面有两个任务 blockblock2,串行队列遵循fifo原则:first  in  first out,就先进先出原则,blokc131行加入,先执行,block235行加入后执行.block1中有三个任务3339行打印和block2,block2在两个打印中间,按照程序自上到下执行尼玛问题又来了,为什么block2不是在两个打印任务之间执行?而是在打印结束后执行?ok 这时就要看函数啦~async 这是什么?异步执行~!!要开启新的线程(或是重复利用线程池中已经创建的线程,什么样的线程可以重复利用?这个线程已经执行完它的任务,进入线程池马上销毁的线程才可以重复利用)(开启线程或是获取线程池中重复利用的线程是需要时间成本的)检测到这个函数怎么办?直接返回,不用等这个函数的block执行完就返回.什么意思?执行到35行的时候兵分两路,一路向下执行39行打印,一路从线程池中获取重复利用的线程处理block2的任务.在兵分两路的时候子线程以还没有处理完39行的打印,它的任务没有结束啊!为什么处理block2没有创建新的线程?因为需要时间和控件成本.GCD为我们做了优化,(怎么优化的我们不用操心~~看不到源码这是个迷,不过看到了也不一定看得懂!哈哈所以不创建新的线程,等子线程1执行完他的任务,我们重复利用它!ok说完了,

.了解了上图,我们再来看下面的代码

我把35行的函数换成了sync同步执行函数,看打印结果,2.3没有打印!这就是传说中的死锁.什么意思?36 ,39行没有打印,程序在等待,卡住了.不能正常向下执行了!

分析一下原因:

1>点击屏幕调用test方法,主线程打印2542,主线程不用我们创建.系统自动创建.上面已经提到原理就不再赘述,直接来重点

2>31行代码做了这几件事:1block1任务添加到队列串行queue,2>利用async函数开启新的子线程1处理block1任务.

3>当执行到35行代码时做了这几件事情:1>block2添加到串行队列queue,2>sync函数不会开启新的线程,只能在当前线程执行任务

4>ok现在我们分析一下是什么情况:1>queue当中有两个任务,block1block2.2>只有一个线程:子线程1,31行创建的.queue串行执行任务,要等block1执行完才能执行block2任务.啥意思?31行创建的子线程1要执行完block1才能执行block2.执行到35block2任务的时候要等待block1执行完,可是程序自上而下执行,尼玛block2不执行完block1就不会执行完!你懂了么?block2所在的是sync函数不能开启新的线程,只能和block1共用一个线程,这个线程在处理block1,现在的问题是没有线程处理block2的任务~!!!所以就出现了传说中的死锁!别尼玛问我为啥主线程不处理block2的任务!我会让你的老板开除你的!还没懂?最后说一遍:程序自上而下执行知道吧?那么block1执行完时不时需要block1里面的所有代码都执行完啊?可是到了35block2没有开启新的线程,只能和block1共用一个线程,现在这个线程在处理block1的任务,要等block1执行完才能执行block2的任务.所以程序就卡住了.ok还不懂?看上面正确的代码第35行我们呢用的是async函数,它能开启一个全新的线程来处理block2任务,且不用等到block2执行完这个函数就返回了!函数返回啥意思----就是继续向下执行了.ok说完了.别告诉我你还没

:有了上面的分析相信小伙伴们有了一定的了解,再来分析一下下面的代码是不是死锁?

所在哪里了?

是死锁,锁在64行的代码.

分析一下原因:

1>主线程执行47, 71行打印之后进入 休眠状态等待下次点击屏幕,在两个打印之间检测到54async不等block1执行完继续向下.ok没问题

2>54行将block1加入到queue队列,async函数开启新的线程执行block1,block1任务代码书讯执行  56行打印

3>58行检测到async函数不等block2执行完继续向下执行,62行打印,

4>执行到64 sync函数 没有开启新的线程,要和block1共用一个线程,造成死锁

5>分析一下现在什么情况:queue中有3个任务,block1,block2,block3,顺序执行,为什么卡在64?不是58?58行开启了一个新的线程来处理block2,所以不是这里.block3没有开启线程要用别人的线程,用谁的呢?你看它在哪个block.她在block1里面,block154行开启了线程正在处理block1,所以现在block2没人处理.就造成死锁.

6>那么为什么block2没有打印呢?有线程处理他的任务啊?这是要看队列queue,三个任务顺序执行,block1执行完了么?没有,所以block2不会打印.ok说完了!有疑问?block2?好吧 来看下面代码.我把64行的函数换了.

为什么是这个打印顺序呀?

1>主线程优先处理,所以 0,6先打印,

2>为什么135这个顺序打印丫?135在同一个线程中,block1的线程中,代码顺序执行,所以这个顺序

3>为什么2,4打印不是穿插在1,3,5之间呢?1>因为2打印要开启新的线程,有时间成本,啥意思,就是我开启一个线程需要时间.所以他要晚

                                                                               2>135在主线程,优先于子线程处理任务,优先级就比子线程高,所以它晚

                                                                               3>async函数不等待后面block执行完就向下执行,所以它晚,

4>为什么2,4打印没有开启两个线程而是一个线程,因为开启新的线程需要时间和控件成本GCD为我们自动做了优化,重复利用了线程池中执行完本职任务即将销毁的线程.

5>为什么24的打印顺序是这样:1>因为4利用了2的线程,(看线程地址)代码自上而下执行,queueblock2排在block3之前,所以要block2打印完才能打印block3.

 

转:https://www.cnblogs.com/LDSmallCat/p/4910080.html



推荐阅读
  • 深入探讨CPU虚拟化与KVM内存管理
    本文详细介绍了现代服务器架构中的CPU虚拟化技术,包括SMP、NUMA和MPP三种多处理器结构,并深入探讨了KVM的内存虚拟化机制。通过对比不同架构的特点和应用场景,帮助读者理解如何选择最适合的架构以优化性能。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
  • 本文详细介绍了Grand Central Dispatch (GCD) 的核心概念和使用方法,探讨了任务队列、同步与异步执行以及常见的死锁问题。通过具体示例和代码片段,帮助开发者更好地理解和应用GCD进行多线程开发。 ... [详细]
  • 在Linux系统中配置并启动ActiveMQ
    本文详细介绍了如何在Linux环境中安装和配置ActiveMQ,包括端口开放及防火墙设置。通过本文,您可以掌握完整的ActiveMQ部署流程,确保其在网络环境中正常运行。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • Linux 基础命令详解
    本文介绍了在 Linux 系统中常见的命令及其用法。当用户登录系统后,默认提示符会显示为 [root@localhost ~]# 或 [user@localhost ~]$,其中 # 表示当前用户为 root,$ 表示普通用户。我们将深入探讨一些常用的 Linux 命令,帮助初学者更好地理解和使用这些工具。 ... [详细]
  • 本题涉及一棵由N个节点组成的树(共有N-1条边),初始时所有节点均为白色。题目要求处理两种操作:一是改变某个节点的颜色(从白变黑或从黑变白);二是查询从根节点到指定节点路径上的第一个黑色节点,若无则输出-1。 ... [详细]
  • 微软Exchange服务器遭遇2022年版“千年虫”漏洞
    微软Exchange服务器在新年伊始遭遇了一个类似于‘千年虫’的日期处理漏洞,导致邮件传输受阻。该问题主要影响配置了FIP-FS恶意软件引擎的Exchange 2016和2019版本。 ... [详细]
  • 探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ... [详细]
  • 作者:守望者1028链接:https:www.nowcoder.comdiscuss55353来源:牛客网面试高频题:校招过程中参考过牛客诸位大佬的面经,但是具体哪一块是参考谁的我 ... [详细]
  • FinOps 与 Serverless 的结合:破解云成本难题
    本文探讨了如何通过 FinOps 实践优化 Serverless 应用的成本管理,提出了首个 Serverless 函数总成本估计模型,并分享了多种有效的成本优化策略。 ... [详细]
  • 本文详细探讨了HTML表单中GET和POST请求的区别,包括它们的工作原理、数据传输方式、安全性及适用场景。同时,通过实例展示了如何在Servlet中处理这两种请求。 ... [详细]
  • 本文旨在提供一套高效的面试方法,帮助企业在短时间内找到合适的产品经理。虽然观点较为直接,但其方法已被实践证明有效,尤其适用于初创公司和新项目的需求。 ... [详细]
  • Appium + Java 自动化测试中处理页面空白区域点击问题
    在进行移动应用自动化测试时,有时会遇到某些页面没有返回按钮,只能通过点击空白区域返回的情况。本文将探讨如何在Appium + Java环境中有效解决此类问题,并提供详细的解决方案。 ... [详细]
author-avatar
颓废胖胖2502908443
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有