我正在尝试修复代码中的并发竞争条件,我一直在考虑队列。有谁能帮助我理解为什么下面的代码不能在iOS上运行?
class Concurrency {
private var privateStuff: Int = 0
var accessQueue = DispatchQueue(label: "read", qos: DispatchQoS.background, attributes: DispatchQueue.Attributes.concurrent, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.workItem, target: nil)
var writequeue = DispatchQueue(label: "write")
var stuff: Int {
get {
var result: Int!
accessQueue.sync {
result = privateStuff
}
return result
}
set {
accessQueue.suspend()
writequeue.sync {
privateStuff = newValue
}
accessQueue.resume()
}
}
}
我仍然有一个竞争条件,所以Xcode说,如果我在这个上面运行大量的reader/writer。
我遗漏了什么吗?谢谢
最佳答案
看起来这个解决方案适合您的问题:
https://medium.com/@oyalhi/dispatch-barriers-in-swift-3-6c4a295215d6
数据竞争条件是由您正在使用两个不同的队列这一事实给出的。当另一个线程请求属性的getter时,没有什么不阻止其他线程在setter中挂起accessQueue
。
像文章中所描述的链接中有几种方法可以解决这个读者-作者的问题。
我最喜欢的是障碍。
另外,我会对那些队列进行防御,将它们设置为private let
而不是vars,以避免一些优秀的同事将mainQueue作为accessQueue传递,从而导致主线程上的线程锁。
所以整件事看起来是这样的:
class Concurrency {
private var privateStuff: String = 🖕
private let queue = DispatchQueue(label: "read-write", qos: DispatchQoS.background, attributes: DispatchQueue.Attributes.concurrent, autoreleaseFrequency: DispatchQueue.AutoreleaseFrequency.workItem, target: nil)
var stuff: String {
get {
var result: String!
queue.sync {
result = privateStuff
}
return result
}
set {
queue.async(flags: .barrier) {
privateStuff = newValue
}
}
}
}