因此,我的代码使用并发调度队列和屏障标志来支持并行读取,但在写入时阻止读取/写入:
struct SafeDict<Element> {
private var dict = [String: Element]()
private var queue = DispatchQueue(label: "WriteQueue", attributes: .concurrent)
func get(_ key: String) -> Element? {
queue.sync { return dict[key] }
}
mutating func set(_ key: String, value: Element) {
queue.sync(flags: .barrier) { dict[key] = value }
}
}
var safeDict = SafeDict<Int>()
for i in 1...4 {
DispatchQueue.global().async {
switch i {
case 1:
safeDict.get("one")
case 2:
safeDict.set("one", value: 1) // Waits for get (good)
case 3:
safeDict.get("one") // Runs after set in parallel
case 4:
safeDict.get("two") // Runs after set in parallel
default:
print("done")
}
}
}
但由于参与者函数是异步的,并行读取将相互等待.如何才能干净利落地避免这种情况呢?
我能想到的一种替代方法是不使用参与者,而是使用两个异步方法(设置).而GET将等待一项既定的任务,如果不是零的话.但这似乎太乏味了.
actor SafeDictActor<Element> {
private var dict = [String: Element]()
func get(_ key: String) -> Element? { dict[key] }
func set(_ key: String, value: Element) { dict[key] = value }
}
let safeDictActor = SafeDictActor<Int>()
for i in 1...4 {
Task {
switch i {
case 1:
await safeDictActor.get("one")
case 2:
await safeDictActor.set("one", value: 1) // Waits for get (good)
case 3:
await safeDictActor.get("one") // waits for set (good)
case 4:
await safeDictActor.get("two") // waits for previous get (bad)
default:
print("done")
}
}
}