在属性声明中,原子和非原子意味着什么?

@property(nonatomic, retain) UITextField *userName;
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName;

这三者之间的操作差异是什么?


当前回答

原子(默认)默认为Atomic:如果不键入任何内容,则属性为原子的如果您尝试从它,您将返回一个有效值。它不做任何保证关于这个值可能是什么,但你会得到好的数据,而不是只是垃圾记忆。如果您有多个线程或多个进程指向一个变量,一个线程可以读取,另一个线程可以写入。如果他们同时命中时间,读取器线程保证获得以下两个值之一:在改变之前或改变之后。什么原子没有给你任何形式的保证可能会得到。原子通常与线程安全相混淆,这是不正确的。你需要保证你的线程安全其他方式。然而,atomic将保证,如果您尝试阅读,你会得到某种价值。非原子的另一方面,非原子的,正如你可能猜到的,只是意味着,“不要做原子的事情。”你失去的是保证你总是要得到一些东西。如果你试着在写,你可以取回垃圾数据。但另一方面,你去快一点。因为原子财产必须发挥一些魔力为了保证你会得到一个值,它们有点慢。如果这是一个你经常访问的财产,你可能想放弃降到非原子,以确保你不会导致那样的速度处罚

在此处查看更多信息:https://realm.io/news/tmi-objective-c-property-attributes/

其他回答

了解差异的最佳方法是使用以下示例。

假设有一个名为“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仍然可以并行执行。

Atomic是线程安全的,它很慢,而且它很好地保证(不保证)无论有多少线程试图访问同一区域,都只提供锁定值。使用atomic时,在该函数中编写的一段代码成为关键部分的一部分,一次只能执行一个线程。

它只保证螺纹安全;它不能保证这一点。我的意思是,你们为你们的汽车雇佣了一名专家司机,但这并不能保证汽车不会发生事故。然而,可能性仍然微乎其微。

原子——它无法分解,所以结果是意料之中的。使用非原子-当另一个线程访问内存区域时,它可以修改它,因此结果是意外的。

代码对话:

原子使属性线程的getter和setter安全。例如,如果你写了:

self.myProperty = value;

是线程安全的。

[myArray addObject:@"Abc"] 

不是线程安全的。

我在这里找到了原子和非原子财产的一个很好的解释。以下是一些相关文本:

“原子”意味着它不能分解。在OS/编程术语中,原子函数调用是一个不能中断的调用——必须执行整个函数,并且在完成之前,不能通过操作系统通常的上下文切换将其从CPU中移出。万一你不知道:由于CPU一次只能做一件事,操作系统会在很小的时间段内对所有正在运行的进程轮流访问CPU,从而产生多任务的错觉。CPU调度器可以(并且确实)在进程执行的任何时间点中断进程,即使是在函数调用中间。因此,对于像更新共享计数器变量这样的操作,如果两个进程可以同时尝试更新变量,则必须“原子”地执行这些操作,即,每个更新操作必须完整完成,然后才能将任何其他进程交换到CPU上。所以我猜测,在这种情况下,原子意味着属性读取器方法不能被中断,实际上意味着该方法读取的变量不能中途更改其值,因为其他线程/调用/函数被交换到CPU上。

因为原子变量不能被中断,所以它们在任何时候包含的值(线程锁)都保证不会被破坏,尽管确保这个线程锁会使对它们的访问变慢。另一方面,非原子变量不能保证这一点,但确实提供了快速访问的奢侈。总之,当您知道变量不会被多个线程同时访问时,可以使用非原子的,这样可以加快速度。

原子=螺纹安全

非原子=无线程安全

螺纹安全:

如果实例变量在从多个线程访问时行为正确,则它们是线程安全的,而不考虑运行时环境对这些线程执行的调度或交织,并且调用代码部分没有额外的同步或其他协调。

在我们的背景下:

如果一个线程更改了实例的值,则所有线程都可以使用更改的值,并且一次只有一个线程可以更改该值。

在何处使用原子:

如果要在多线程环境中访问实例变量。

原子的含义:

没有非原子的速度快,因为非原子的运行时不需要任何看门狗的工作。

在何处使用非原子:

如果实例变量不会被多个线程更改,您可以使用它。它可以提高性能。

原子:

原子保证以原子的方式访问财产。例如,它总是返回一个完全初始化的对象,一个线程上的属性的任何获取/设置都必须在另一个线程访问它之前完成。

如果你想象一下下面的函数同时出现在两个线程上,你就会明白为什么结果不好看。

-(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不同,它不能确保每次都返回完全初始化的对象。

赞成的意见:执行速度极快。

欺骗:在多线程的情况下,可能会产生垃圾值。