Swift4变量是原子的吗?
我想知道
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() } } 输出如下所示,锁定了lock.lock()和lock.unlock(). 3 3 3 4 5 ... 2999 3000 输出如下,lock.lock()和lock.unlock取消注释. 1 2 3 4 5 ... 2999 3000 我的问题 所以,在我看来,有一个时刻,例如,queueA和queueB得到的计数等于15,并且它们都将计数增加1(count = 1),所以即使有两个增加,计数也应该是16执行. 但是上面的三个队列只是在第一个开始时随机开始计算,然后一切都按照预期进行. 总而言之,我的问题是为什么计数有序打印? 更新: func increase() { lock.lock() self.count += 1 array.append(self.count) lock.unlock() } 2.输出方式: @IBAction func tapped(_ sender: Any) { let testObjc = Test() testObj.testA() DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+3) { print(self.testObj.array) } } 没有NSLock的输出: 使用NSLock输出: [1,2,3,…,2999,3000] 解决方法
不,默认情况下,Swift属性不是原子的,是的,很可能你会遇到多线程问题,多线程使用该属性的过时值,这个属性刚刚更新.
但在我们开始追逐之前,让我们看看原子财产是什么.
现在在你的代码中我们不是在谈论一个原子属性,因为= operation实际上被分成了至少三个操作: >获取当前值,将其存储在CPU寄存器中 即使setter是原子的,我们也可能会遇到两个线程“同时”到达#1并尝试在相同值上运行的情况. 所以这里的问题应该是:是()一个原子操作吗? 现在回到实际的代码,这是“救援”你的打印电话.增量和存储操作需要很短的时间,而打印需要更长的时间.这就是为什么你似乎没有遇到竞争条件,因为多个线程可以使用过时值的窗口非常小. 请尝试以下操作:取消注释打印调用,并在足够大的时间后打印计数值,以便所有后台线程完成(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() 您现在将看到锁定版本提供一致的结果,而非锁定版本则不会. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |