You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift Array的sorted方法对本地数组副本是否具备线程安全性?

问题根因

你对线程安全的防护只覆盖了字典读取生成数组的过程,没有覆盖数组内元素的访问安全,直接导致了野地址访问崩溃。

具体触发场景

  • 数组存储的是对象引用而非独立拷贝

valuesArray()生成的新数组仅拷贝了Device对象的引用指针,所有元素仍然和deviceDict中存储的对象指向同一块内存地址。如果其他线程在排序过程中将某个Device实例从deviceDict中移除,且没有其他强引用持有该实例,实例会被系统回收,排序闭包访问该实例的serialID属性时就会触发野指针崩溃。

  • 通知回调线程不可控

NSNotification的回调执行线程和通知发送线程完全一致,从崩溃栈可以看到排序逻辑运行在第9号子线程,说明通知是从后台线程发出的。此时如果主线程或其他后台线程同时修改、销毁Device实例,就会出现多线程访问冲突。

  • 字符串属性的多线程访问同样会引发崩溃

即使是String?类型的属性,多线程无锁读写也会出现内存损坏:如果Device是Objective-C类,serialID的底层实现是NSString类型,赋值过程中被其他线程读取会拿到非法的中间态内存地址;即使是纯Swift String类型,无锁并发读写也会触发内存异常。

  • (可选检查)SafeDict的写操作可能未加防护

你给出的SafeDict实现仅包含读逻辑,如果对字典的写操作没有使用queue.async(flags: .barrier)保证读写互斥,读操作和写操作可能并行执行,生成的devices数组本身就可能包含非法的元素引用。

修复方案

  1. 生成devices数组时对所有Device实例做深拷贝,保证排序操作的是完全独立的实例,不受其他线程修改影响
  2. 所有对Device实例的读写操作统一加锁,或者限定所有Device实例的修改、读取操作都在主线程执行
  3. 收到通知后先切换到主线程再执行排序、刷新UI的逻辑,避免后台线程执行UI相关操作的同时出现多线程访问冲突
  4. 补全SafeDict的写操作防护,所有修改字典的逻辑都使用barrier标识保证并发队列的读写互斥

内容的提问来源于stack exchange,提问作者davidgyoung

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 19:54:02