关于原子属性,Apple的文档如下:
这意味着合成的访问器确保值为 始终通过getter方法完全检索或通过 setter方法,即使同时调用访问器 不同的主题。
“完全检索”或“完全设定”是什么意思? 为什么“完全检索”或“完全设置”不足以保证线程安全?
注意:我知道在SO上有很多关于原子性的帖子,请不要将其标记为重复,除非该票证专门解决了上述问题。阅读帖子后,我仍然不完全了解原子属性。
答案 0 :(得分:2)
Atomic意味着对getter / setter的调用是同步的。这样,如果一个线程在另一个线程获取它的同时设置该属性,则获得该属性的那个保证获得有效的返回值。如果没有它是原子的,则getter可能会检索垃圾值或指向立即释放的对象的指针。当它是原子的时,它还将确保如果两个线程同时尝试设置它,则会等待另一个线程完成。如果它不是原子的,并且两个线程试图同时设置它,那么最终可能会写入一个垃圾值,或者可能是保留过度/不足或者过度/不足释放的对象。
所以基本上,如果正在设置属性,则设置或获取它的任何其他调用将等待方法返回。如果获得该属性,任何其他获取或设置它的调用将等到该完成。
这有时足以满足线程的安全性,具体取决于它的用途。但是,对于线程安全,您通常需要的不仅仅是这种级别的同步。例如,如果一个线程上的一个代码块获取该值,则对其进行一些更改,并希望在没有其他线程同时更改它的情况下再次设置它。您必须执行其他同步以确保在获得之前锁定它,直到您随后设置它为止。如果你想获得一个对象并对该对象进行一些更改而没有另一个线程试图在其上同时进行更改,你会想要做同样的事情。
答案 1 :(得分:1)
“完全设置”和“完全检索”表示下面的代码将始终打印“0x11111111”或“0x22222222”。它永远不会打印“0x11112222”或“0x11221122”之类的东西。如果没有atomic
或其他一些适当的线程同步,某些CPU架构上的某些数据类型允许进行部分读取或部分更新。
// Thread 1
while (true) x = 0x11111111;
// Thread 2
while (true) x = 0x22222222;
// Thread 3
while (true) printf("0x%x\n", x);
答案 2 :(得分:0)
这意味着在写入中途时永远不会访问该值。它将始终是一个预期的值或另一个,从不是一个不完全改变的位模式。
仅保证线程安全是不够的,因为确保变量的值要么完全写入要么根本不写入,这不足以使所有使用该变量的代码都是线程安全的。例如,可能有两个变量需要一起更新(经典示例是将信用从一个帐户转移到另一个帐户),但另一个线程中的代码可以看到一个带有新值的变量和一个带有旧值的变量。
通常,您需要为整个系统实现同步,因此原子变量提供的保证几乎不会在很多时候产生影响。