上下文
我们有一个事件跟踪模块,当报告条件触发时,会批量报告收集到的事件。收集的每个事件都标有唯一的事件索引
。为了保证唯一性,事件索引
生成的工作放在一个同步队列中,以便其他线程调用该模块。
代码片段
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)
})
堆栈
这是调用栈的一部分
问题
为什么会造成死锁?我的代码片段有什么问题?
最佳答案
您的代码中存在循环依赖:
- 共享实例的初始化需要一个
EventIndexManager
对象。 EventIndexManager
的初始化函数需要一个已初始化的共享实例。
这行不通,因为变量 sharedManager
的初始化时间不早于 init 函数之后。您不应在 init 函数中访问 sharedManager
或 sharedMananger()
。
关于ios - 使用NSUserDefaults的同步操作GCD队列导致的死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42546693/