在属性声明中,原子和非原子意味着什么?
@property(nonatomic, retain) UITextField *userName;
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName;
这三者之间的操作差异是什么?
在属性声明中,原子和非原子意味着什么?
@property(nonatomic, retain) UITextField *userName;
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName;
这三者之间的操作差异是什么?
当前回答
原子=螺纹安全
非原子=无线程安全
螺纹安全:
如果实例变量在从多个线程访问时行为正确,则它们是线程安全的,而不考虑运行时环境对这些线程执行的调度或交织,并且调用代码部分没有额外的同步或其他协调。
在我们的背景下:
如果一个线程更改了实例的值,则所有线程都可以使用更改的值,并且一次只有一个线程可以更改该值。
在何处使用原子:
如果要在多线程环境中访问实例变量。
原子的含义:
没有非原子的速度快,因为非原子的运行时不需要任何看门狗的工作。
在何处使用非原子:
如果实例变量不会被多个线程更改,您可以使用它。它可以提高性能。
其他回答
原子:
原子保证以原子的方式访问财产。例如,它总是返回一个完全初始化的对象,一个线程上的属性的任何获取/设置都必须在另一个线程访问它之前完成。
如果你想象一下下面的函数同时出现在两个线程上,你就会明白为什么结果不好看。
-(void) setName:(NSString*)string
{
if (name)
{
[name release];
// what happens if the second thread jumps in now !?
// name may be deleted, but our 'name' variable is still set!
name = nil;
}
...
}
赞成的意见:每次返回完全初始化的对象是多线程情况下的最佳选择。
欺骗:性能受到影响,执行速度稍慢
非原子:
与Atomic不同,它不能确保每次都返回完全初始化的对象。
赞成的意见:执行速度极快。
欺骗:在多线程的情况下,可能会产生垃圾值。
首先最简单的回答是:第二个例子之间没有区别。默认情况下,属性访问器是原子的。
非垃圾收集环境中的原子访问器(即,当使用retain/release/autorelease时)将使用锁来确保另一个线程不会干扰值的正确设置/获取。
有关更多信息以及创建多线程应用程序时的其他注意事项,请参阅苹果Objective-C 2.0文档的“性能和线程”部分。
苹果的文档中对此进行了解释,但下面是一些实际发生情况的示例。
请注意,没有“atomic”关键字,如果不指定“nonatomic(非原子)”,则属性是原子的,但显式指定“atomic”将导致错误。
如果不指定“非原子”,则该属性是原子的,但如果需要,在最近的版本中仍然可以显式指定“原子”。
//@property(nonatomic, retain) UITextField *userName;
//Generates roughly
- (UITextField *) userName {
return userName;
}
- (void) setUserName:(UITextField *)userName_ {
[userName_ retain];
[userName release];
userName = userName_;
}
现在,原子变体有点复杂:
//@property(retain) UITextField *userName;
//Generates roughly
- (UITextField *) userName {
UITextField *retval = nil;
@synchronized(self) {
retval = [[userName retain] autorelease];
}
return retval;
}
- (void) setUserName:(UITextField *)userName_ {
@synchronized(self) {
[userName_ retain];
[userName release];
userName = userName_;
}
}
基本上,原子版本必须使用锁以保证线程安全,并且还会碰撞对象上的引用计数(以及自动释放计数以平衡它),从而保证该对象对于调用者存在,否则如果另一个线程正在设置该值,则存在潜在的争用条件,导致引用计数降至0。
实际上,根据财产是标量值还是对象,以及保留、复制、只读、非原子等交互方式,这些东西的工作方式有很多不同的变体。一般来说,属性合成器只知道如何为所有组合做“正确的事情”。
Atomic是线程安全的,它很慢,而且它很好地保证(不保证)无论有多少线程试图访问同一区域,都只提供锁定值。使用atomic时,在该函数中编写的一段代码成为关键部分的一部分,一次只能执行一个线程。
它只保证螺纹安全;它不能保证这一点。我的意思是,你们为你们的汽车雇佣了一名专家司机,但这并不能保证汽车不会发生事故。然而,可能性仍然微乎其微。
原子——它无法分解,所以结果是意料之中的。使用非原子-当另一个线程访问内存区域时,它可以修改它,因此结果是意外的。
代码对话:
原子使属性线程的getter和setter安全。例如,如果你写了:
self.myProperty = value;
是线程安全的。
[myArray addObject:@"Abc"]
不是线程安全的。
原子:通过使用NSLOCK锁定线程来确保线程安全。
非原子:由于没有线程锁定机制,因此无法确保线程安全。