线程安全和写/读安全之间有什么区别?

时间:2018-10-07 13:59:33

标签: ios

在iOS中,atomic仅保证写入/读取安全。不是线程安全的。有人说线程安全性更高。我对他们之间的差异感到困惑。 w / r safe有时可以用来实现线程安全吗? 当原子不能保证
线程安全。为什么我们在多个线程中使用它?

2 个答案:

答案 0 :(得分:0)

作为示例,请考虑在32位处理器上运行的64位long整数类型。由于处理器一次只能使用32位,因此更新long的过程类似于以下伪汇编:

mov %r1, [addr]
mov %r2, [addr+4]

如果变量以0开头,并且您尝试向其写入0xffffffff,则这两条指令之间的执行可能会中断,并且其他读取内存的代码将读取值{{1} }。

原子更新保证整个值以某种方式或其他方式作为单个操作写入,因此尽管(由于它不是线程安全的),您不能保证确切地知道另一个线程何时会看到更新的值,但是 保证每当它看到一个值时,它都不会部分更新,而是一个完全正确(即使可能已过时)的值。该概念可以扩展到相关的更复杂的数据类型。

答案 1 :(得分:0)

atomic保证仅对单个属性执行独占执行,也就是说,您不能同时在一个对象上读/写单个属性。

但是,atomic不能保证同一对象的两个不同属性可以同时被独占访问/写入。

给出的最常见示例是具有public enum Direction { NORTH, EAST, SOUTH, WEST; private static final Map<Direction, Direction> OPPOSITES = ImmutableMap.of( NORTH, SOUTH, EAST, WEST, SOUTH, NORTH, WEST, EAST ); public Direction oppositeDirection() { return OPPOSITES.get(this); } } Person属性的firstName类。

lastName

在最坏的情况下,let person = Person() // Thread 1 person.firstName = "Name1" person.lastName = "LastName1" // Thread 2 person.firstName = "Name2" person.lastName = "LastName2" 可能会变成personName1 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) 上的设置firstNamelastName一起执行。