ios - 使用NSUserDefaults的同步操作GCD队列导致的死锁

标签 ios swift xcode

上下文

我们有一个事件跟踪模块,当报告条件触发时,会批量报告收集到的事件。收集的每个事件都标有唯一的事件索引。为了保证唯一性,事件索引生成的工作放在一个同步队列中,以便其他线程调用该模块。

代码片段

class EventIndexManager {

fileprivate static let sharedInstance = EventIndexManager()
fileprivate var eventIndexQueue = DispatchQueue(label: "com.johnkui.EventIndex.SyncQueue")
fileprivate var curEventIndex: UInt64 = 0

static func sharedManager() -> EventIndexManager {
    return sharedInstance
}

func getEventIndex() -> UInt64 {
    eventIndexQueue.sync {
        if self.curEventIndex != 0 {
            self.curEventIndex += 1
        } else {
            if let prevEventIndex = UserDefaults.standard.value(forKey: "event_index") as? UInt64 {
                self.curEventIndex = prevEventIndex + 1
            } else {
                self.curEventIndex = 1
            }
        }
        
        let curEventIndex = self.curEventIndex
        eventIndexQueue.async {
            let eventIndex = self.curEventIndex > curEventIndex ? self.curEventIndex : curEventIndex
            UserDefaults.standard.set(eventIndex, forKey: "event_index")
            UserDefaults.standard.synchronize()
        }
    }
    
    return self.curEventIndex
}
}

class EventTask: Taskable {
var event: String
var parameters: [String : Any]
var eventIndex: UInt64

init(event: String, parameters: [String : Any]) {
    self.event = event
    self.parameters = parameters
    self.eventIndex = EventIndexManager.sharedManager().getEventIndex()
    super.init()
}
}


DispatchQueue.main.async(execute: { () -> Void in
                let task = EventTask(event: event, parameters: i18nParameters)
                self.tasks.append(task)
            })

堆栈

这是调用栈的一部分

calling stack

问题

为什么会造成死锁?我的代码片段有什么问题?

最佳答案

您的代码中存在循环依赖:

  1. 共享实例的初始化需要一个EventIndexManager对象。
  2. EventIndexManager 的初始化函数需要一个已初始化的共享实例。

这行不通,因为变量 sharedManager 的初始化时间不早于 init 函数之后。您不应在 init 函数中访问 sharedManagersharedMananger()

关于ios - 使用NSUserDefaults的同步操作GCD队列导致的死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42546693/

相关文章:

ios - 将 UnityAds 添加到我的 Swift 游戏项目

iphone - iOS4中文本的阴影效果

ios - 如何使用 IPv6 设置 Restund Turn 服务器

ios - NSMutableString的appendFormat不能追加多个项

ios - Swift 覆盖子类中的协议(protocol)方法

ios - 如何在 SpriteKit 中取消一个特定的 SKAction.movebyX?

iOS Objective-C 低延迟音频播放,如 SoundPool

ios - 使用 Xcode 和 UICollectionView 中的 Assets 目录管理 800 个图像

xcode - 使用带有 OS X 框架目标和 iOS 静态库目标的 Xcode 项目构建错误

objective-c - 核心数据 - 将实体保存为 pList/字典