在属性声明中,原子和非原子意味着什么?
@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不同,它不能确保每次都返回完全初始化的对象。
赞成的意见:执行速度极快。
欺骗:在多线程的情况下,可能会产生垃圾值。
其他回答
原子的
是默认行为将确保当前进程在另一个进程访问变量之前由CPU完成速度不快,因为它可以确保整个过程完全完成
非原子的
不是默认行为更快(对于合成代码,即使用@property和@synthetic创建的变量)非线程安全当两个不同的进程同时访问同一变量时,可能会导致意外行为
原子:
原子保证以原子的方式访问财产。例如,它总是返回一个完全初始化的对象,一个线程上的属性的任何获取/设置都必须在另一个线程访问它之前完成。
如果你想象一下下面的函数同时出现在两个线程上,你就会明白为什么结果不好看。
-(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文档的“性能和线程”部分。
默认值是原子的,这意味着无论何时使用该属性都会降低性能,但它是线程安全的。Objective-C的作用是设置一个锁,因此只要执行setter/getter,只有实际线程才能访问变量。
具有ivar_internal的属性的MRC示例:
[_internal lock]; //lock
id result = [[value retain] autorelease];
[_internal unlock];
return result;
因此,后两项相同:
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName; // defaults to atomic
另一方面,非原子对代码没有任何影响。所以只有当你自己编写安全机制时,它才是线程安全的。
@property(nonatomic, retain) UITextField *userName;
关键字根本不必写为第一个属性属性。
别忘了,这并不意味着整个属性是线程安全的。只有setter/getter的方法调用是。但是如果您使用setter,然后同时使用2个不同线程的getter,那么它也可能会被破坏!
了解差异的最佳方法是使用以下示例。
假设有一个名为“name”的原子字符串属性,如果您从线程A调用[self-setName:@“A”],从线程B调用[selfsetName:@“B”],并从线程C调用[self name],那么不同线程上的所有操作都将串行执行,这意味着如果一个线程正在执行setter或getter,那么其他线程将等待。
这使得属性“name”读/写安全,但如果另一个线程D同时调用[namerelease],那么这个操作可能会产生崩溃,因为这里没有setter/getter调用。这意味着一个对象是读/写安全的(ATOMIC),但不是线程安全的,因为另一个线程可以同时向该对象发送任何类型的消息。开发人员应确保此类对象的线程安全。
如果属性“name”是非原子的,那么上面示例中的所有线程(A、B、C和D)将同时执行,产生任何不可预测的结果。在原子的情况下,A、B或C中的任何一个将首先执行,但D仍然可以并行执行。