在iOS中,atomic仅保证写入/读取安全。不是线程安全的。有人说线程安全性更高。我对他们之间的差异感到困惑。 w / r safe有时可以用来实现线程安全吗?
当原子不能保证
线程安全。为什么我们在多个线程中使用它?
答案 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"
可能会变成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)
上的设置firstName
和lastName
一起执行。