我近年来看过WWDC GCD 的谈话,我认为有一段代码片段有问题。它是关于使用 DispatchQueues 使属性线程安全。
class MyObject {
private var internalState: Int
private let internalQueue: DispatchQueue // Serial or Concurrent?
var state: Int {
get {
return internalQueue.sync { internalState }
}
set (newState) {
internalQueue.sync { internalState = newState }
}
}
}
他们使用 DispatchQueue 来锁定属性。但我认为此代码段无效,因为 internalQueue 可能是并发的。因此,如果我们从两个不同的 DispatchQueues / Threads 调用setter,如果该内部队列不是串行的,那么它也可能导致线程问题吗?因为在我的理解中,sync只保存调用线程,并在任务完成时继续。你觉得这个片段怎么样?我错了吗?
答案 0 :(得分:11)
我希望展示另一种方法,使您能够同时阅读,但在使用调度屏障进行书写时阻止所有内容。
class MyObject {
private var internalState: Int
private let internalQueue = DispatchQueue(label: "reader-writer", attributes: .concurrent))
var state: Int {
get {
return internalQueue.sync { internalState }
}
set (newState) {
internalQueue.async(flags: .barrier) { internalState = newState }
}
}
}
使用这种方法,读取可以在队列上同时发生,但由于屏障,写入是专门执行的。
这只是对Matt Galloway撰写的 Effective Objective C 2.0 一书中解释的方法的Swift 3转换。
答案 1 :(得分:7)
但我认为这个片段无效,因为internalQueue可能是并发的
但它不是并发的。默认情况下,您创建的调度队列是串行的。这就是技术的重点(和例子)。