Objective-C中的原子属性与线程安全性

Dou*_*ith 27 multithreading objective-c thread-safety atomicity ios

在我读过的大多数讨论中,它表明使属性原子不能保证它是线程安全的,它只是保证返回的值不会是一个对象写入它而另一个对象的垃圾.试图同时阅读它.

我理解这不是线程安全的,因为第三个对象可能正在编写它,而访问它的对象不会被垃圾回收,但是当多个对象同时写入它时,它不能完全确定它将返回哪个值时间,它可能会得到他们的任何价值观.

因此,当我们说它不会返回垃圾时,垃圾是否意味着如果一个对象是非原子的并且一个对象试图访问它而另一个对象正在写入它,那么它可能会在写入中间得到结果,并且只能获得写入所带来的部分不完整版本的更改?这就是"垃圾"在这个意义上意味着什么,以及什么原子属性有助于防止?

Bin*_*ian 38

atomicObjective C中的属性保证您永远不会看到部分写入.当a @property具有该属性时atomic,不可能仅部分地写入该值.二传手是这样的:

- (void)setProp:(NSString *)newValue {
    [_prop lock];
    _prop = newValue;
    [_prop unlock];
}
Run Code Online (Sandbox Code Playgroud)

因此,如果两个线程想要同时写入值@"test"和@"otherTest",则在任何给定时间该属性只能是属性的初始值或@"test"或@"otherTest". nonatomic更快,但该值是垃圾值,没有@"test"/ @"otherTest"(thx @Gavin)或任何其他垃圾值的部分字符串.

但是 atomic只使用简单的线程安全.它没有被保证. Appledoc说如下:

考虑一个XYZPerson对象,其中使用来自一个线程的原子访问器来更改人的名字和姓氏.如果另一个线程同时访问这两个名称,则原子getter方法将返回完整的字符串(不会崩溃),但不能保证这些值将是相对于彼此的正确名称.如果在更改之前访问了第一个名称,但在更改后访问了最后一个名称,则最终会出现一个不一致,不匹配的名称对.

我根本没遇到使用原子的问题.我设计了代码,原子属性没有问题.

  • 你永远不会看到类似"teerTest"的东西,因为将属性设置为字符串只是设置一个指向Objective-C对象的指针.那么你可能会看到的是一个垃圾指针,但是从来没有你想要设置的两个字符串的混合(除非碰巧是在其他地方定义的字符串,就像你实际上在你的某个地方有一个字符串"teerTest"应用程序,垃圾指针实际上设法指向它). (9认同)
  • 我从Apple文档中理解的是:如果你有两个原子属性,你需要从这两个生成结果数据,而线程以任何方式访问或修改它们,那么你将获得结果(保证)但可能不正确,我感觉很好,而不是手动编写线程安全的代码. (2认同)
  • 对我来说[这篇关于处理器级别的原子和非原子操作的文章](http://preshing.com/20130618/atomic-vs-non-atomic-operations/) 对理解**如何**一个值可能特别有趣部分写入。 (2认同)

Rob*_*vey 6

回答你的第三段; 基本上是的.线程正在写入数字时无法读取原子序数.

例如,如果一个线程写入了原子四字节数的前两个字节,并且在另一个线程上请求读取该数字,则该读取必须等到所有四个字节都被写入.

相反,如果一个线程已写入非原子四字节数的前两个字节,并且此时在另一个线程上请求读取该数字,它将读取前两个新数据字节,但将获取旧数据来自前两个字节的写操作.

  • 究竟哪些类型是自然原子的是特定于平台的.在x86的情况下,至少应该有4个字节的整数.结构或双打不会. (2认同)