我想知道Swift 4变量是否是原子的.所以我做了以下测试.
以下是我的测试代码.
class Test {
var count = 0
let lock = NSLock()
func testA() {
count = 0
let queueA = DispatchQueue(label: "Q1")
let queueB = DispatchQueue(label: "Q2")
let queueC = DispatchQueue(label: "Q3")
queueA.async {
for _ in 1...1000 {
self.increase()
}
}
queueB.async {
for _ in 1...1000 {
self.increase()
}
}
queueC.async {
for _ in 1...1000 {
self.increase()
}
}
}
///The increase() method:
func increase() {
// lock.lock()
self.count += 1
print(count)
// lock.unlock()
}
}
Run Code Online (Sandbox Code Playgroud)
输出如下lock.lock()并lock.unlock() 评论.
3
3
3
4
5
...
2999
3000
Run Code Online (Sandbox Code Playgroud)
输出如下lock.lock()并lock.unlock 取消注释.
1
2
3
4
5
...
2999
3000
Run Code Online (Sandbox Code Playgroud)
我的问题
如果count变量是非原子的,则queueA,queueB和queueC应该异步调用increase(),这导致随机访问和打印count.
所以,在我看来,有一个时刻,例如,queueA和queueB count等于15,并且它们都增加count1(count += 1),所以即使执行了两次增加,计数也应该是16.
但是上面的三个队列只是在第一个开始时随机开始计算,然后一切都按照预期进行.
总而言之,我的问题是为什么count有序印刷?
更新:问题已解决,如果您想按照我的方式进行实验,请执行以下更改.
1.改变increase()到下面,你会得到合理的输出.
func increase() {
lock.lock()
self.count += 1
array.append(self.count)
lock.unlock()
}
Run Code Online (Sandbox Code Playgroud)
2.输出方式:
@IBAction func tapped(_ sender: Any) {
let testObjc = Test()
testObj.testA()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+3) {
print(self.testObj.array)
}
}
Run Code Online (Sandbox Code Playgroud)
不,默认情况下,Swift属性不是原子的,是的,很可能你会遇到多线程问题,多线程使用该属性的过时值,这个属性刚刚更新.
但在我们开始追逐之前,让我们看看原子财产是什么.
原子属性是具有原子设置器的属性 - 即,当setter执行它的工作时,其他想要访问(获取或设置)属性的线程被阻止.
现在在你的代码中我们不是在谈论一个原子属性,因为该+=操作实际上被拆分为至少三个操作:
即使setter是原子的,我们也可能会遇到两个线程"同时"到达#1并尝试在相同值上运行的情况.
所以这里的问题应该是:是increase()原子操作吗?
现在回到实际的代码,这print是"救援"你的电话.增量和存储操作需要很短的时间,而打印需要更长的时间.这就是为什么你似乎没有遇到竞争条件,因为多个线程可以使用过时值的窗口非常小.
请尝试以下操作:同时取消注释print调用,并count在足够大的时间后打印值以使所有后台线程完成(2秒应足以进行1000次迭代):
let t = Test()
t.testA()
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
// you're likely to get different results each run
print(t.count)
}
RunLoop.current.run()
Run Code Online (Sandbox Code Playgroud)
您现在将看到锁定版本提供一致的结果,而非锁定版本则不会.
| 归档时间: |
|
| 查看次数: |
1516 次 |
| 最近记录: |