IOS 线程死锁详细介绍
发布时间 - 2026-01-10 23:20:07 点击率:次iOS线程死锁

前言:
在chat view的开发过程中,添加了“混合标签添加与显示”,app出现发送图片会出现卡死的情况,但过了大约30~40 second后会恢复正常。
问题分析:
因为没有任何报错与提示,只能根据表面现象慢慢分析,经过多次测试与观察得出以下规律:
(1)发送表情与文本不会发生该情况,只有发送图片才会发生app界面卡死的情况。(主线程阻塞,与大文件上传有关)
(2)app卡死一定时间后会恢复正常,但时间不定,大约范围在30~40 second。(主线程解除阻塞,与系统某些机制有关)
(3)当界面中有gif图时才会发生,界面中全是移动端本地图片是能顺利发送。(与gif下载有关)
根据上述现象,可以总结为:主线程阻塞,过后因通信通信失败而阻塞解除。
因为与gif图的下载有关,于是分析gif的下载实现,gif图的下载由以下代码实现。
NSData *gifImageData = [NSDatadataWithContentsOfURL:model.imageRemoteURL];
FLAnimatedImage *FLAImage = [FLAnimatedImageanimatedImageWithGIFData:gifImageData];
其中,关于NSData的静态方法dataWithContentsOfURL的说明中有以下使用说明。
Important
Do not use this synchronous method to request network-based URLs. For network-based URLs, this method can block the current thread for tens of seconds on a slow network, resulting in a poor user experience, and in iOS, may cause your app to be terminated.
这里说明了要尽量避免使用dataWithContentsOfURL从网络下载资源,因为它会阻塞当前线程,若下载的文件比较大而网络又不好就会带来很差的用户体验,对于iOS设备还可能引起app被迫终止。
虽然只需要把dataWithContentsOfURL放置到别的线程中实现,又或者使用NSURLConnect、NSURLSession中的异步请求方法也能解决问题,但本质上引起这问题是因为调用dataWithContentsOfURL时网络环境差吗?
明显不是,因为测试环境是模拟器,模拟器的cpu、网络通信是比真机要好的,只有GPU是不如真机。而且问题的出现规律是固定。
但dataWithContentsOfURL已经解析了为什么主线程阻塞,那么现在需要解析为什么会阻塞那么长的时间。
CPU分析结果:
图中的标记的那段是发生异常情况时的CPU的情况。从CPU图上可以更加肯定线程是并没有死掉的,而且进入了无法响应的状态,因此可以判断出发生线程死锁的情况。
线程死锁
死锁的概念:
死锁是进程死锁的简称,是由Dijkstra于1965年研究银行家算法时首先提出来的。它是计算机操作系统乃至并发程序设计中最难处理的问题之一。实际上,死锁问题不仅在计算机系统中存在,在我们日常生活中它也广泛存在。
我们先看看这样一个生活中的例子:在一条河上有一座桥,桥面较窄,只能容纳一辆汽车通过,无法让两辆汽车并行。如果有两辆汽车A和B分别由桥的两端驶上该桥,则对于A车来说,它走过桥面左面的一段路(即占有了桥的一部分资源),要想过桥还须等待B车让出右边的桥面,此时A车不能前进;对于B车来说,它走过桥面右边的一段路(即占有了桥的一部分资源),要想过桥还须等待A车让出左边的桥面,此时B车也不能前进。两边的车都不倒车,结果造成互相等待对方让出桥面,但是谁也不让路,就会无休止地等下去。这种现象就是死锁。如果把汽车比做进程,桥面作为资源,那麽上述问题就描述为:进程A占有资源R1,等待进程B占有的资源Rr;进程B占有资源Rr,等待进程A占有的资源R1。而且资源R1和Rr只允许一个进程占用,即:不允许两个进程同时占用。结果,两个进程都不能继续执行,若不采取其它措施,这种循环等待状况会无限期持续下去,就发生了进程死锁。
上图是一张描述一个简单的死锁模型的图,首先Thread1锁定占有资源Y,Thread2锁定占有资源X,但同时相互向对方请求资源,因此都无法释放自身资源去访问下一个资源,结果两个线程相互阻塞。
死锁的四个充分必要条件
从以上分析可见,如果在计算机系统中同时具备下面四个必要条件时,那麽会发生死锁。换句话说,只要下面四个条件有一个不具备,系统就不会出现死锁。
〈1〉互斥条件。即某个资源在一段时间内只能由一个进程占有,不能同时被两个或两个以上的进程占有。这种独占资源如CD-ROM驱动器,打印机等等,必须在占有该资源的进程主动释放它之后,其它进程才能占有该资源。这是由资源本身的属性所决定的。如独木桥就是一种独占资源,两方的人不能同时过桥。
〈2〉不可抢占条件。进程所获得的资源在未使用完毕之前,资源申请者不能强行地从资源占有者手中夺取资源,而只能由该资源的占有者进程自行释放。如过独木桥的人不能强迫对方后退,也不能非法地将对方推下桥,必须是桥上的人自己过桥后空出桥面(即主动释放占有资源),对方的人才能过桥。
〈3〉占有且申请条件。进程至少已经占有一个资源,但又申请新的资源;由于该资源已被另外进程占有,此时该进程阻塞;但是,它在等待新资源之时,仍继续占用已占有的资源。还以过独木桥为例,甲乙两人在桥上相遇。甲走过一段桥面(即占有了一些资源),还需要走其余的桥面(申请新的资源),但那部分桥面被乙占有(乙走过一段桥面)。甲过不去,前进不能,又不后退;乙也处于同样的状况。
〈4〉循环等待条件。存在一个进程等待序列{P1,P2,...,Pn},其中P1等待P2所占有的某一资源,P2等待P3所占有的某一源,......,而Pn等待P1所占有的的某一资源,形成一个进程循环等待环。就像前面的过独木桥问题,甲等待乙占有的桥面,而乙又等待甲占有的桥面,从而彼此循环等待。
上面我们提到的这四个条件在死锁时会同时发生。也就是说,只要有一个必要条件不满足,则死锁就可以排除。
项目中死锁的形成与解决
根据以上理论,以及断点调试,可以分析得项目的形成,如下图所描述。
因此只要让同步下载时不会挂起主线程就可以避免线程死锁的情况发生。因此项目中使用NSURLConnet的同步请求方法实现下载即可, 因为它不会挂起主线程,还能让其他线程往主线程中添加代码块block。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
# IOS
# 线程死锁
# 线程死锁详解
# 线程死锁实例
# iOS中的线程死锁实例详解
# 详解iOS 多线程 锁 互斥 同步
# 详解iOS多线程之2.NSThread的加锁@synchronized
# iOS中多网络请求的线程安全详解
# 浅析iOS应用开发中线程间的通信与线程安全问题
# iOS开发常用线程安全锁
# 死锁
# 过桥
# 的人
# 必要条件
# 所占
# 就会
# 中有
# 要想
# 又不
# 后会
# 恢复正常
# 空出
# 两辆
# 桥上
# 还须
# 挂起
# 这是
# 两人
# 是因为
# 都不
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
html5如何设置样式_HTML5样式设置方法与CSS应用技巧【教程】
在Oracle关闭情况下如何修改spfile的参数
Laravel策略(Policy)如何控制权限_Laravel Gates与Policies实现用户授权
如何在橙子建站中快速调整背景颜色?
创业网站制作流程,创业网站可靠吗?
JavaScript如何操作视频_媒体API怎么控制播放
极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?
Laravel如何操作JSON类型的数据库字段?(Eloquent示例)
齐河建站公司:营销型网站建设与SEO优化双核驱动策略
公司网站制作价格怎么算,公司办个官网需要多少钱?
如何在云主机快速搭建网站站点?
Laravel怎么实现软删除SoftDeletes_Laravel模型回收站功能与数据恢复【步骤】
Laravel怎么做数据加密_Laravel内置Crypt门面的加密与解密功能
零服务器AI建站解决方案:快速部署与云端平台低成本实践
Laravel如何使用Facades(门面)及其工作原理_Laravel门面模式与底层机制
javascript中的数组方法有哪些_如何利用数组方法简化数据处理
如何用虚拟主机快速搭建网站?详细步骤解析
太平洋网站制作公司,网络用语太平洋是什么意思?
C++用Dijkstra(迪杰斯特拉)算法求最短路径
laravel怎么使用数据库工厂(Factory)生成带有关联模型的数据_laravel Factory生成关联数据方法
ChatGPT怎么生成Excel公式_ChatGPT公式生成方法【指南】
Laravel如何使用withoutEvents方法临时禁用模型事件
谷歌浏览器如何更改浏览器主题 Google Chrome主题设置教程
奇安信“盘古石”团队突破 iOS 26.1 提权
如何在不使用负向后查找的情况下匹配特定条件前的换行符
Laravel Admin后台管理框架推荐_Laravel快速开发后台工具
如何快速登录WAP自助建站平台?
如何在云服务器上快速搭建个人网站?
Laravel怎么上传文件_Laravel图片上传及存储配置
LinuxShell函数封装方法_脚本复用设计思路【教程】
Laravel Seeder怎么填充数据_Laravel数据库填充器的使用方法与技巧
jQuery validate插件功能与用法详解
Laravel Eloquent模型如何创建_Laravel ORM基础之Model创建与使用教程
详解CentOS6.5 安装 MySQL5.1.71的方法
C++时间戳转换成日期时间的步骤和示例代码
Zeus浏览器网页版官网入口 宙斯浏览器官网在线通道
购物网站制作费用多少,开办网上购物网站,需要办理哪些手续?
Linux系统命令中tree命令详解
bing浏览器学术搜索入口_bing学术文献检索地址
制作ppt免费网站有哪些,有哪些比较好的ppt模板下载网站?
如何快速生成ASP一键建站模板并优化安全性?
Laravel如何实现邮件验证激活账户_Laravel内置MustVerifyEmail接口配置【步骤】
如何撰写建站申请书?关键要点有哪些?
如何在云主机上快速搭建网站?
javascript中数组(Array)对象和字符串(String)对象的常用方法总结
制作公司内部网站有哪些,内网如何建网站?
打造顶配客厅影院,这份100寸电视推荐名单请查收
大连网站制作费用,大连新青年网站,五年四班里的视频怎样下载啊?
儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?
网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?

