nonatomic
是否有意义?我想知道这两个属性之间的区别:
@property (nonatomic) BOOL myBool;
@property BOOL myBool;
nonatomic
是否有意义?@property (nonatomic) BOOL myBool;
@property BOOL myBool;
技术上讲,它们是不同的,但实际上除非您编写自己的访问器,否则它们并没有区别。
让我解释一下。对于对象指针属性,比如@property NSObject *foo
,如果您使用synthesize访问器,生成的代码中会有明显而重要的差异。这在苹果文档中有描述,其中指出如果该属性是原子性的(如果您未指定nonatomic,则默认为原子性),则合成的访问器将锁定该对象。
因此,对于对象属性,简单地说:nonatomic更快,但不是线程安全的;atomic(您无法指定,但它是默认值)是线程安全的,但可能较慢。
(注意:如果您习惯了Java,可以将使用nonatomic
视为类似于不指定synchronized
,而不指定nonatomic
则类似于指定synchronized
。换句话说,atomic = synchronized)
@property (getter=isEmptyThingo) BOOL emptyThingo;
...
- (BOOL)isEmptyThingo
{
Thingo *thingo = [self deriveTheThingo];
if ([thingo length] == 0) {
return YES;
}
return NO;
}
谁知道在deriveTheThingo
中发生了什么!?
好吧,这有点牵强,但重点是isEmptyThingo - 我们的getter看起来不太原子化,对吗?如果一个线程正在派生thingo,而另一个线程调用查找它是否为空会发生什么。
长话短说:该属性不是原子的。因此,我们应该声明它为原子的。
因此,我的原始答案合格:如果您自己编写此属性并使用@synthesize,则它们可能相同,但通常不应将它们视为相同。
作为经验法则,如果您不需要多线程支持-通常在像UIViewControllers这样的UI代码中不需要-则只需声明所有内容为非原子性。
在一个x位的架构中(比如:32位、64位等),任何小于或等于x位的值都将被原子地读取或写入。这是任何合理硬件实现的属性。
默认的原子属性意味着属性值总是整体设置或获取,无视其他线程正在做什么。这只对超过架构位数的属性才是一个问题。对于任何其他类型,非原子性都会被编译器完全忽略。
例如:
@property struct { int d; } flag;
@property (atomic) struct { float x; float y; } point;
@property (atomic,copy) NSString *s;
struct { int d; }
已经是原子型的,因此访问器不需要互斥。
struct { float x, float y}
如果不是原子的,则可能处于不一致状态。例如:两个线程分别设置{1,2}
和{3,4}
,这两个写入操作可能会重叠,导致结构体最终的值为每个集合中的一个值:{1,4}
。
原子属性有助于线程安全,避免竞态条件造成的不一致值或内存管理问题。但仅凭这一点并不能保证线程安全,因为它并未解决死锁、饥饿、可见性等其他问题。
是的。 nonatomic
不是一个内存管理关键字,它与线程安全有关。此外,属性默认情况下是原子性的(没有显式声明为 nonatomic),因此你列出的这两个声明之间存在差异。