关于ios:原子属性和用法

Atomic property and usage

我读过很多StackOverflow的答案,比如原子属性线程安全吗?什么时候使用@原子?或者Objtovi-C中的原子属性与线程安全,但我对此有疑问:

如果我错了,请纠正我,这就像我使用的是一个计数变量,我用原子属性声明了它,目前它的值是5。它是由两个线程访问的,第一个线程的计数值增加了2,第二个线程的计数值减少了1,根据我的理解,这就像第一个线程的计数值增加了,现在是5+2=7;之后只有第二个线程可以访问计数变量,只减少了1,即7。- 1=6?


First thread that is increasing count value by 2

这不是原子操作,atomic对你没有任何帮助。这是(至少)三个独立的原子操作:

  • 读取值
  • 增值
  • 写入值

这是经典的多作家竞赛条件。另一个线程可以在"读取值"和"写入值"之间进行读取。在您的示例中,最终结果可以是4,这样增加操作完全丢失(读取5,B读取5,A+2,写入7,B -1,B写入4)。

EDCOX1(0)所要解决的问题是,在许多平台特定的情况下,"读取值"和"写入值"甚至不是原子操作。以上实际上可以是5种操作,例如:

  • 读下词
  • 读上词
  • 增值
  • 写下低位字
  • 写上一个字

如果没有atomic,另一个线程可能会在"写下一个字"和"写上一个字"之间读取,并得到一个从未写入的垃圾值(一个值的一半和另一个值的一半)。通过使用atomic,您可以确保读者始终收到一个"合法"的值(在某个时刻编写的值)。但这不是什么承诺。

但是正如您提供的问题中所指出的,如果您需要使读和写成为原子的,那么您几乎肯定需要的不仅仅是它,因为您还希望使"增加值"成为原子的。因此,在实践中,atomic很少有用。如果你不需要它,它就慢了。如果你确实需要它,它可能是不够的。


基于原子的属性,当两个线程访问同一对象以增加或减少值时,您可以理解这一点,就像两个线程都访问了相同的/完整的值(即5),但是第一个线程尝试更新该值时,该值被锁定,没有其他线程可以同时更新该值,但是第二个线程也具有相同的值(即5)。并且只能在计数对象更新被第一个线程退出时更新。


好的,线程可能不会按顺序执行,创建的第一个线程可能在第二个线程之后运行。如果线程按照您描述的顺序执行,那么所提到的行为是好的。但我认为您对线程安全有一个误解。

我鼓励您阅读更多关于并发编程指南和线程安全的内容。