gpt4 book ai didi

swift - Xcode 错误地报告 Swift Access 竞争条件

转载 作者:行者123 更新时间:2023-11-30 10:35:58 25 4
gpt4 key购买 nike

我相信 XCode 在我的 SynchronizedDictionary 中错误地报告了 Swift Access Race - 是这样吗?

我的 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
}
}
}
}

以下测试代码将触发“Swift Access Race”问题(当为该方案打开Thread Sanitizer时):

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 {
syncDict["\(i)"] = "\(i)"
}
setExpectation.fulfill()
}

queue.async {
for i in 0...100 {
_ = syncDict["\(i)"]
}
getExpectation.fulfill()
}

self.wait(for: [setExpectation, getExpectation], timeout: 30)

Swift Race Access 如下所示:

Swift Race Access我真的没想到这里会出现访问竞争条件,因为 SynchronizedDictionary 应该处理并发。

我可以通过在测试中将获取和设置包装在 DispatchQueue 中来解决该问题,类似于 SynchronizedDictionary 的实际实现:

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)

...但这已经发生在 SynchronizedDictionary 内部 - 那么为什么 Xcode 会报告访问竞争条件? - 是 Xcode 有问题,还是我遗漏了什么?

最佳答案

线程清理程序报告 Swift access race

var syncDict = SynchronizedDictionary<String, String>()

结构,因为在

处有一个变异访问(通过下标 setter )
syncDict["\(i)"] = "\(i)"

从一个线程,以及对同一结构的只读访问(通过下标 getter)

_ = syncDict["\(i)"]

来自不同的线程,没有同步。

这与对私有(private)var字典属性的访问冲突,或者与下标方法内部发生的情况无关。如果您将结构简化为

,您将获得相同的“Swift access race”
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> { ... }

这是一个引用类型,下标 setter 不再改变 syncDict 变量(现在是指向实际对象存储的“指针”)。进行此更改后,您的代码运行时不会出现错误。

关于swift - Xcode 错误地报告 Swift Access 竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58025624/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com