为什么原子在复杂对象的线程安全性方面是不够的

时间:2017-03-28 12:16:20

标签: objective-c

为了线程安全,

daterange(possible_start, (possible_start + possible_length)::date)关键字应用于类的属性。

atomic的用法对于原始数据类型是线程安全的,但对于复杂对象(模态对象)则不是。为什么?

提前感谢您的回复!

更新

如果atomic是包含属性Personnameage的类。

考虑

address

对象@property(atomic, strong) Person *adam;线程安全多远?

2 个答案:

答案 0 :(得分:2)

即使在编辑之前,这确实是What's the difference between the atomic and nonatomic attributes?的欺骗,但这并不明显。

由于经常引用该答案,我添加以下内容以强调线程安全实际上是关于某种事务模型,其中读取和写入受到控制,使得系统是当读或写发生时,处于已知的积分状态。

单个属性的

atomicity在多个依赖属性发挥作用时也无法保证线程安全。

考虑:

 @property(atomic, copy) NSString *firstName;
 @property(atomic, copy) NSString *lastName;
 @property(readonly, atomic, copy) NSString *fullName;

在这种情况下,线程A可以通过调用setFirstName:然后调用setLastName:来重命名对象。在此期间,线程B可以在线程A的两个调用之间调用fullName,并将接收与旧的姓氏一起使用的新名字。

要解决此问题,您需要交易模型。即一些其他类型的同步和/或排除,允许在更新依赖属性时排除对fullName的访问。

答案 1 :(得分:2)

差异源于这样一个事实:一个对象带有自己的方法和行为,这可能会导致对其setter和getter之外的对象进行更改。

Atomic关键字仅在编译器合成的setter和getter之间提供线程同步。

这通常足以为原始属性提供线程安全性,因为它的底层ivar只能通过其setter和getter访问。

但是,对于对象属性,这只会为指针提供对象的线程安全性。 setter和getter本身会自动同步,但该对象的其他一些方法可能是从不同的线程修改它,并且该属性整体上不是线程安全的。如果你想保证安全,你必须与所有可能修改对象的方法实现同步。

例如,以下不可变字符串应该是线程安全的,因为它只能通过访问器修改

@property (atomic, strong) NSString * immutableString;

虽然以下可变的不会是线程安全的

@property (atomic, strong) NSMutabeString * mutableString;