dispatch_apply执行计算密集型任务时单线程占满CPU且程序无法结束
问题排查与解决方案
核心根因
1. 0值输入触发死循环
dispatch_apply传入的迭代下标i从0开始计数,当i=0时,three_n_plus_one函数初始计算值为0:
内层3n+1循环中,0永远满足current != 1的判断条件,且每次除以2后仍为0,直接触发无限死循环。
而dispatch_apply作为同步接口,会优先分配部分block到调用线程(即主线程)执行来减少线程调度开销,当死循环的block刚好分配到主线程时,就会出现主线程CPU占用100%、dispatch_apply永远不会返回的现象,完全匹配你遇到的表现。
2. 全局变量数据竞争
两个全局变量longest、highest存在多线程并发读写,无任何同步保护,属于C/Objective-C的未定义行为,可能出现变量值撕裂、缓存不一致、编译器错误优化等问题,即使修复死循环问题后也可能出现计算结果错误。
修复方案
- 修复死循环:调整初始传入的计算值,在调用
three_n_plus_one时传入i+1,或者在函数开头增加判断:if (start == 0) start = 1,避开0值输入。 - 修复数据竞争:对全局变量的读写增加同步保护,可以选择以下任意一种方案:
- 用
@synchronized关键字包裹全局变量的读写逻辑 - 使用
os_unfair_lock等轻量锁做读写保护 - 改为线程局部缓存统计结果,所有线程执行完成后再合并全局最大值,彻底避免运行时锁竞争,更适合CPU密集型计算场景
- 用
内容的提问来源于stack exchange,提问作者Tambarskjelve
相关产品推荐
相关产品推荐

