Swift Xcode错误地报告了快速访问竞争条件
我相信XCode在我的<代码>同步字典代码>中错误地报告了快速访问竞赛-或者是这样吗 我的Swift Xcode错误地报告了快速访问竞争条件,swift,xcode,multithreading,race-condition,ios-multithreading,Swift,Xcode,Multithreading,Race Condition,Ios Multithreading,我相信XCode在我的同步字典中错误地报告了快速访问竞赛-或者是这样吗 我的SynchronizedDictionary如下所示: public struct SynchronizedDictionary<K: Hashable, V> { private var dictionary = [K: V]() private let queue = DispatchQueue( label: "SynchronizedDictionary",
SynchronizedDictionary
如下所示:
public struct SynchronizedDictionary<K: Hashable, V> {
private var dictionary = [K: V]()
private let queue = DispatchQueue(
label: "SynchronizedDictionary",
qos: DispatchQoS.userInitiated,
attributes: [DispatchQueue.Attributes.concurrent]
)
public subscript(key: K) -> V? {
get {
return queue.sync {
return self.dictionary[key]
}
}
mutating set {
queue.sync(flags: .barrier) {
self.dictionary[key] = newValue
}
}
}
}
…但这已经发生在
SynchronizedDictionary
中-那么为什么Xcode报告访问竞争条件呢是Xcode出错了,还是我遗漏了什么?线程消毒器向
从一个线程访问,并且以只读方式访问相同的结构(通过下标getter)
来自不同的线程,没有同步
这与对private var dictionary
属性的访问冲突无关,也与下标方法内部发生的情况无关。如果将结构简化为
public struct SynchronizedDictionary<K: Hashable, V> {
private let dummy = 1
public subscript(key: String) -> String {
get {
return key
}
set {
}
}
}
public struct SynchronizedDictionary{
私有let dummy=1
公共下标(键:String)->String{
得到{
返回键
}
设置{
}
}
}
因此,这是线程消毒剂的正确报告,而不是错误
一种可能的解决方案是定义一个类:
公共类同步字典{…}
这是一种引用类型,下标设置器不再变异
syncDict
变量(现在是实际对象存储中的“指针”)。通过该更改,您的代码运行时不会出错。您的两个异步块可以分配给由并发队列控制的不同线程。这两个线程中的任何一个都可以先执行。我怀疑它因此在抱怨代码不能保证setter在getter之前运行。您可以通过将其设置为串行队列并查看错误是否消失来测试我的理论。谢谢您的反馈。我同意你的观点,用序列号替换并发队列可以解决这个问题。然而,这违背了SynchronizedDictionary的目的——能够同时访问它。@PhillipMills最后,setter和getter都进入了并发队列,setter阻塞了一切。我看不出当所有内容都被阻止并等待setter完成时,这会如何导致竞争条件。@PelleStenildColtau:请注意,在setter中,您可以异步调度(使用屏障),参见示例。啊,这是变量syncDict
的竞争条件,这与syncDict
中的任何内容都没有关系:)
let accessQueue = DispatchQueue(
label: "AccessQueue",
qos: DispatchQoS.userInitiated,
attributes: [DispatchQueue.Attributes.concurrent]
)
var syncDict = SynchronizedDictionary<String, String>()
let setExpectation = XCTestExpectation(description: "set_expectation")
let getExpectation = XCTestExpectation(description: "get_expectation")
let queue = DispatchQueue(label: "SyncDictTest", qos: .background, attributes: [.concurrent])
queue.async {
for i in 0...100 {
accessQueue.sync(flags: .barrier) {
syncDict["\(i)"] = "\(i)"
}
}
setExpectation.fulfill()
}
queue.async {
for i in 0...100 {
accessQueue.sync {
_ = syncDict["\(i)"]
}
}
getExpectation.fulfill()
}
self.wait(for: [setExpectation, getExpectation], timeout: 30)
var syncDict = SynchronizedDictionary<String, String>()
syncDict["\(i)"] = "\(i)"
_ = syncDict["\(i)"]
public struct SynchronizedDictionary<K: Hashable, V> {
private let dummy = 1
public subscript(key: String) -> String {
get {
return key
}
set {
}
}
}
public class SynchronizedDictionary<K: Hashable, V> { ... }