在属性声明中,原子和非原子意味着什么?
@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;
这三者之间的操作差异是什么?
当前回答
原子的
是默认行为将确保当前进程在另一个进程访问变量之前由CPU完成速度不快,因为它可以确保整个过程完全完成
非原子的
不是默认行为更快(对于合成代码,即使用@property和@synthetic创建的变量)非线程安全当两个不同的进程同时访问同一变量时,可能会导致意外行为
其他回答
我在这里找到了原子和非原子财产的一个很好的解释。以下是一些相关文本:
“原子”意味着它不能分解。在OS/编程术语中,原子函数调用是一个不能中断的调用——必须执行整个函数,并且在完成之前,不能通过操作系统通常的上下文切换将其从CPU中移出。万一你不知道:由于CPU一次只能做一件事,操作系统会在很小的时间段内对所有正在运行的进程轮流访问CPU,从而产生多任务的错觉。CPU调度器可以(并且确实)在进程执行的任何时间点中断进程,即使是在函数调用中间。因此,对于像更新共享计数器变量这样的操作,如果两个进程可以同时尝试更新变量,则必须“原子”地执行这些操作,即,每个更新操作必须完整完成,然后才能将任何其他进程交换到CPU上。所以我猜测,在这种情况下,原子意味着属性读取器方法不能被中断,实际上意味着该方法读取的变量不能中途更改其值,因为其他线程/调用/函数被交换到CPU上。
因为原子变量不能被中断,所以它们在任何时候包含的值(线程锁)都保证不会被破坏,尽管确保这个线程锁会使对它们的访问变慢。另一方面,非原子变量不能保证这一点,但确实提供了快速访问的奢侈。总之,当您知道变量不会被多个线程同时访问时,可以使用非原子的,这样可以加快速度。
默认值是原子的,这意味着无论何时使用该属性都会降低性能,但它是线程安全的。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,那么它也可能会被破坏!
原子:通过使用NSLOCK锁定线程来确保线程安全。
非原子:由于没有线程锁定机制,因此无法确保线程安全。
原子:
原子保证以原子的方式访问财产。例如,它总是返回一个完全初始化的对象,一个线程上的属性的任何获取/设置都必须在另一个线程访问它之前完成。
如果你想象一下下面的函数同时出现在两个线程上,你就会明白为什么结果不好看。
-(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不同,它不能确保每次都返回完全初始化的对象。
赞成的意见:执行速度极快。
欺骗:在多线程的情况下,可能会产生垃圾值。
如果您使用的是atomic,这意味着线程将是安全且只读的。如果您使用的是非原子的,这意味着多个线程访问变量,并且线程不安全,但它执行速度很快,执行了读写操作;这是一种动态类型。