@property(nonatomic, retain) UITextField *userName; @property(atomic, retain) UITextField *userName; @property(retain) UITextField *userName;
这三者在操作上有什么区别?
假设您正在 @synthesizing 方法实现,原子与非原子会更改生成的代码。如果您正在编写自己的 setter/getter,则 atomic/nonatomic/retain/assign/copy 只是建议性的。(注意:@synthesize 现在是 LLVM 最新版本中的默认行为。也不需要声明实例变量;它们也会自动合成,并且会_在其名称前添加一个前缀以防止意外直接访问)。
_
使用“原子”,合成的 setter/getter 将确保始终从 getter 返回整个值或由 setter 设置,而不管任何其他线程上的 setter 活动。也就是说,如果线程 A 位于 getter 的中间,而线程 B 调用 setter,则实际可行的值——很可能是一个自动释放的对象——将返回给 A 中的调用者。
在nonatomic中,没有做出这样的保证。因此,nonatomic比“原子”要快得多。
nonatomic
“原子”不做的是对线程安全做出任何保证。如果线程 A 同时调用 getter,而线程 B 和 C 使用不同的值调用 setter,则线程 A 可能会返回三个值中的任何一个——在调用任何 setter 之前的那个值或传递给 setter 的值中的任何一个在 B 和 C 中。同样,对象可能以 B 或 C 中的值结束,无法判断。
确保数据完整性——多线程编程的主要挑战之一——是通过其他方式实现的。
添加到此:
atomicity当多个依赖属性在起作用时,单个属性的属性也不能保证线程安全。
atomicity
考虑:
@property(atomic, copy) NSString *firstName; @property(atomic, copy) NSString *lastName; @property(readonly, atomic, copy) NSString *fullName;
在这种情况下,线程 A 可以通过调用setFirstName:然后调用来重命名对象setLastName:。同时,线程 B 可能会fullName在线程 A 的两次调用之间调用,并会收到新的名字和旧的姓氏。
setFirstName:
setLastName:
fullName
为了解决这个问题,您需要一个事务模型。即某种其他类型的同步和/或排除允许一个人fullName在更新依赖属性时排除访问。