【发布时间】:2019-03-12 08:29:59
【问题描述】:
在 iOS 中,原子只是保证写/读安全。不是线程安全的。有人说线程安全是更高级别的。我对他们的区别感到困惑。 w/r safe 有时可以用来实现线程安全吗?
而当原子不能保证
线程安全。为什么我们在多个线程中使用它?
【问题讨论】:
标签: ios
在 iOS 中,原子只是保证写/读安全。不是线程安全的。有人说线程安全是更高级别的。我对他们的区别感到困惑。 w/r safe 有时可以用来实现线程安全吗?
而当原子不能保证
线程安全。为什么我们在多个线程中使用它?
【问题讨论】:
标签: ios
例如,考虑在 32 位处理器上运行的 64 位 long 整数类型。由于处理器一次只运行 32 位,更新 long 看起来像这样的伪程序集:
mov %r1, [addr]
mov %r2, [addr+4]
如果变量以值 0 开头,而您尝试向其写入 0xffffffff,则执行可能会在这两条指令之间中断,而其他读取内存的代码读取值 0x0000ffff。
原子更新保证整个值以某种方式写入单个操作,因此虽然(因为它不是线程安全的)你不能保证另一个线程何时会看到更新的值,你是保证无论何时它确实看到一个值,它不会被部分更新,而是一个完全正确的(即使可能是过时的)值。这个概念可以扩展到更复杂的相关数据类型。
【讨论】:
atomic 保证仅在单个属性上独占执行,也就是说,您不能同时在对象上读取/写入单个属性。
但是,atomic 不保证同一对象的两个不同属性可以同时独占访问/写入。
为说明这一点而给出的最常见示例是具有firstName 和lastName 属性的Person 类。
let person = Person()
// Thread 1
person.firstName = "Name1"
person.lastName = "LastName1"
// Thread 2
person.firstName = "Name2"
person.lastName = "LastName2"
在最坏的情况下,person 最终可能是Name1 LastName 2 或Name2 LastName1。
这是更高级别的线程安全发挥作用的地方,我使用锁定/解锁作为平台/语言特定锁定机制的占位符。
let person = Person()
// Thread 1
lock(person)
person.firstName = "Name1"
person.lastName = "LastName1"
unlock(person)
// Thread 2
lock(person)
person.firstName = "Name2"
person.lastName = "LastName2"
unlock(person)
通过这种锁定/解锁,我们保证在person 上设置firstName 和lastName 一起执行。
【讨论】: