我试图通过允许多个线程读取和写入共享状态来模拟竞争条件。但不知何故,最终结果是正确的。下面是我用来模拟行为的代码。
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let queue = DispatchQueue(label: "my-queue", qos: .userInitiated, attributes: [.concurrent, .initiallyInactive])
var val = 0
let group = DispatchGroup()
group.enter()
queue.async {
for _ in 0..<100 {
val += 1
}
group.leave()
}
group.enter()
queue.async {
for _ in 0..<100 {
val += 1
}
group.leave()
}
queue.activate()
group.notify(queue: DispatchQueue.main) {
print("Done incrementing final value is \(val)")
}
输出为:完成递增的最终值为200
问题是当多个线程正在读取和写入单个值时,最终输出是200?
答案 0 :(得分:1)
这可能不会在游乐场发生。尝试在真实的应用程序中运行它。
两个线程互相干扰的唯一方法是,如果一个线程在另一个线程读取值并增加它之间读取val
的值。你可能只是幸运,因为阅读val
和用递增值写的时间之间的时间非常小。将阅读和写作分开并引入延迟(使用usleep
),您将看到竞争条件:
let queue = DispatchQueue(label: "my-queue", qos: .userInitiated, attributes: [.concurrent, .initiallyInactive])
var val = 0
let group = DispatchGroup()
group.enter()
queue.async {
for _ in 0..<100 {
let value = val
usleep(10_000)
val = value + 1
print("val = \(val)")
}
group.leave()
}
group.enter()
queue.async {
for _ in 0..<100 {
let value = val
usleep(9_000)
val = value + 1
print("val = \(val)")
}
group.leave()
}
queue.activate()