原子和非原子属性之间有什么区别?

Ale*_*yne 1828 properties atomic objective-c ios nonatomic

财产申报中的含义atomicnonatomic含义是什么?

@property(nonatomic, retain) UITextField *userName;
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName;
Run Code Online (Sandbox Code Playgroud)

这三者之间的运作区别是什么?

bbu*_*bum 1747

最后两个是相同的; "atomic"是默认行为(请注意,它实际上不是关键字;仅在缺少时指定nonatomic - atomic在最近版本的llvm/clang中添加为关键字).

假设你是@synthesizing方法实现,原子与非原子会改变生成的代码.如果您正在编写自己的setter/getter,则atomic/nonatomic/retain/assign/copy仅仅是建议性的.(注意:@synthesize现在是LLVM的最新版本中的默认行为.也不需要声明实例变量;它们也将自动合成,并且将_在其名称前加上以防止意外直接访问).

使用"atomic",合成的setter/getter将确保始终从getter返回整个值或由setter设置,而不管任何其他线程上的setter活动.也就是说,如果线程A位于getter的中间,而线程B调用setter,则实际可行的值 - 一个自动释放的对象,很可能 - 将返回给A中的调用者.

nonatomic,没有这样的保证.因此,nonatomic比"原子"快得多.

什么"原子"并没有做的就是关于线程安全的任何保证.如果线程A与线程B同时调用getter并且C调用具有不同值的setter,则线程A可以获得返回的三个值中的任何一个 - 在调用任何setter之前的值或者传递给setter的任一值在B和C中.同样,对象最终可能会得到B或C的值,无法分辨.

确保数据完整性 - 多线程编程的主要挑战之一 - 是通过其他方式实现的.

添加到此:

atomicity 当多个相关属性在起作用时,单个属性也不能保证线程安全.

考虑:

 @property(atomic, copy) NSString *firstName;
 @property(atomic, copy) NSString *lastName;
 @property(readonly, atomic, copy) NSString *fullName;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,线程A可以通过调用setFirstName:然后调用来重命名对象setLastName:.同时,线程B可以fullName在线程A的两个调用之间调用,并且将接收与旧的姓氏一起的新的名字.

要解决此问题,您需要一个事务模型.即一些其他类型的同步和/或排除,允许fullName在更新依赖属性时排除对访问的访问.

  • 鉴于任何线程安全的代码将执行自己的锁定等,您何时想要使用原子属性访问器?我在思考一个很好的例子时遇到了麻烦. (21认同)
  • @HotLicks另一个有趣的; 在某些体系结构上(不记得哪一个),作为参数传递的64位值可能会在寄存器中传递一半而在堆栈中传递一半.`atomic`防止跨线程半值读取.(这是一个有趣的错误追踪.) (10认同)
  • @bbum有道理.我喜欢你对另一个答案的评论,即线程安全更像是一个模型级别的问题.从IBM线程安全定义:http://ibm.co/yTEbjY"如果一个类正确实现,这是另一种说法符合其规范的方式,没有操作序列(读取或写入公共字段和调用)对于该类的对象,应该能够将对象置于无效状态,观察对象处于无效状态,或者违反任何类的不变量,前置条件或后置条件. (8认同)
  • @congliu线程A返回没有`retain/autorelease`舞蹈的对象.线程B释放对象.线程A开始**热潮**.`atomic`确保线程A具有强引用(+1保留计数)作为返回值. (8认同)
  • 这是一个类似于@StevenKramer的例子:我有一个`@property NSArray*astronomicalEvents;`列出了我想在UI中显示的数据.当应用程序启动指针指向空数组时,应用程序将从Web中提取数据.当Web请求完成时(在不同的线程中),应用程序构建一个新数组,然后以原子方式将该属性设置为新的指针值.它是线程安全的,我不必编写任何锁定代码,除非我遗漏了一些东西.对我来说似乎非常有用. (6认同)
  • 如果你有一个访问者,它将从多个线程读取一个结构(或一个对象),并且你的代码被硬化,"这真的是当前状态",它很有用.也就是说,如果您正在阅读一个结构,该结构具有一些总结当前状态的条目,则原子可以启用安全读取. (3认同)
  • `atomic`现在已成为最近版本clang中的关键字. (3认同)
  • @bugloaf是的 - 你是对的(好点+1).但是,大多数应用程序通常会使用完成块或处理程序来处理"数据可用",这将比仅设置属性(拆除"加载",更新其他状态位等)做更多的工作.无论如何,所有UI更新都必须在主线程上完成.那么,当典型的代码*已经在主队列上进行序列化时,为什么会为所有访问产生"atomic"的开销呢?可以使用"原子"的另一种情况,但现实世界的模式可以满足需要. (2认同)
  • 他们为什么不使用默认的`nonatomic`,因为它经常被使用?然后,你可以写:`@property UIWindow*window`而不是`@property(nonatomic)UIWindow*window`. (2认同)
  • @bugloaf - 我不明白`atomic`是如何在那里服务的.如果属性仅在一个线程中发生变异,则检查属性指针的另一个线程将找到旧指针或新指针.我可以看到`atomic`是重要的,如果有可能有一个部分变异的指针,但我不相信这可能在任何通常的Objective-C平台上. (2认同)
  • **另一个重要的区别是**如果一个线程写了一个原子四字节数的前两个字节,并且在另一个线程上请求读取该数字,*read*必须等待**直到所有四个字节已被写入.相反,如果一个线程写入了非原子四字节数的前两个字节,并且此时在另一个线程上请求读取该数字,它将读取前两个**新**数据字节,但是将从其他两个字节中的先前写操作中获取**旧**数据.http://stackoverflow.com/a/21098554/5175709 (2认同)

Lou*_*arg 358

这在Apple的文档中有解释,但下面是一些实际发生的例子.请注意,没有"atomic"关键字,如果未指定"nonatomic",则属性为atomic,但明确指定"atomic"将导致错误.

//@property(nonatomic, retain) UITextField *userName;
//Generates roughly

- (UITextField *) userName {
    return userName;
}

- (void) setUserName:(UITextField *)userName_ {
    [userName_ retain];
    [userName release];
    userName = userName_;
}
Run Code Online (Sandbox Code Playgroud)

现在,原子变体有点复杂:

//@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_;
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上,原子版本必须采取锁定以保证线程安全,并且还会碰撞对象的引用计数(以及自动释放计数以平衡它),以便保证对象存在对象,否则存在如果另一个线程正在设置该值,则是一个潜在的竞争条件,导致引用计数降至0.

实际上有很多不同的变体,这些东西的工作方式取决于属性是标量值还是对象,以及保留,复制,只读,非原子等交互方式.一般来说,属性合成器只知道如何为所有组合做"正确的事情".

  • 并不是说锁不能"保证线程安全". (9认同)
  • @Louis Gerbarg:我相信如果您尝试分配同一个对象(即:userName == userName_),您的(非原子,保留)setter版本将无法正常工作 (8认同)
  • 你的代码有点误导; 对于原子吸气剂/设定器的同步有***保证.重要的是,`@ property(assign)id delegate;`在任何事情上都没有同步(iOS SDK GCC 4.2 ARM` -Os`),这意味着`[self.delegate delegateMethod:self];`和`foo之间存在竞争. delegate = nil; self.foo = nil; [super dealloc];`.请参阅http://stackoverflow.com/questions/917884/locking-details-of-synthesized-atomic-properties-in-obj-c-2-0 (5认同)

raw*_*w3d 167

原子

  • 是默认行为
  • 在另一个进程访问变量之前,将确保CPU完成当前进程
  • 并不快,因为它确保完整的过程完成

非原子

  • 不是默认行为
  • 更快(对于合成代码,即对于使用@property和@synthesize创建的变量)
  • 不是线程安全的
  • 当两个不同的进程同时访问同一个变量时,可能会导致意外行为


Vij*_*dra 134

理解差异的最佳方法是使用以下示例.

假设存在一个名为"name"的原子字符串属性,如果[self setName:@"A"]从线程A调用,[self setName:@"B"]从线程B调用,并[self name]从线程C 调用,则不同线程上的所有操作将按顺序执行,这意味着一个线程正在执行一个setter或者getter,然后其他线程将等待.

这使得属性"name"读/写安全,但如果另一个线程D [name release]同时调用,则此操作可能会产生崩溃,因为此处不涉及setter/getter调用.这意味着对象是读/写安全的(ATOMIC),但不是线程安全的,因为另一个线程可以同时向对象发送任何类型的消息.开发人员应确保此类对象的线程安全.

如果属性"name"是非原子的,那么上面例子中的所有线程--A,B,C和D将同时执行,产生任何不可预测的结果.在原子的情况下,A,B或C中的任何一个将首先执行,但D仍然可以并行执行.


jus*_*tin 114

这个问题的其他优秀答案已经很好地定义了语法和语义.由于执行性能不够详细,我将添加我的答案.

这三种功能有什么区别?

我一直认为原子作为一个非常好奇的默认.在抽象层面,我们致力于将类的原子属性用作实现100%线程安全性的工具,这是一个极端情况.对于真正正确的多线程程序,程序员的干预几乎肯定是必需的.同时,性能特征和执行还没有详细说明.多年来编写了一些大量多线程的程序后,我一直在声明我的属性,nonatomic因为原子对任何目的都不合理.在讨论原子和非原子属性的细节这个问题时,我做了一些分析,遇到了一些奇怪的结果.

执行

好.我想要澄清的第一件事是锁定实现是实现定义和抽象的.路易斯@synchronized(self)在他的例子中使用- 我已经将此视为混淆的常见原因.实施实际上并没有使用@synchronized(self); 它使用对象级旋转锁.路易斯的插图对于使用我们都熟悉的结构的高级插图是有益的,但重要的是知道它不使用@synchronized(self).

另一个区别是原子属性将保留/释放你的对象在getter中.

性能

这是有趣的部分:在无争议(例如单线程)情况下使用原子属性访问的性能在某些情况下可能非常快.在不太理想的情况下,使用原子访问的成本可能是开销的20倍以上nonatomic.虽然使用7个线程的Contested案例对于三字节结构(2.2 GHz Core i7四核,x86_64)来说慢了44倍.三字节结构是一个非常慢的属性的例子.

有趣的注意事项:三字节结构的用户定义访问器比合成的原子访问器快52倍; 或84%的合成非原子访问器的速度.

有争议案件中的物品也可超过50次.

由于实施中的优化和变化的数量,在这些环境中测量实际影响是非常困难的.您可能经常会听到"信任它,除非您分析并发现它是一个问题".由于抽象级别,实际上很难衡量实际影响.从配置文件收集实际成本可能非常耗时,并且由于抽象,非常不准确.同样,ARC vs MRC可以产生很大的不同.

所以让我们退一步,不再关注属性访问的实现,我们将包括通常的嫌疑人objc_msgSend,并检查一些真实的高级结果,以便NSString无争议的情况下(以秒为单位的值)多次调用getter :

  • MRC | 非原子的 手动实现的getters:2
  • MRC | 非原子的 合成的吸气剂:7
  • MRC | 原子| 合成的吸气剂:47
  • ARC | 非原子的 合成的吸气剂:38(注意:ARC在这里添加参考计数循环)
  • ARC | 原子| 合成的吸气剂:47

正如您可能已经猜到的那样,引用计数活动/循环是原子学和ARC下的重要贡献者.您还会看到有争议案件的更大差异.

虽然我非常关注性能,但我仍然说Semantics First!.同时,性能是许多项目的低优先级.但是,了解您使用的技术的执行细节和成本肯定不会受到伤害.您应该根据自己的需要,目的和能力使用正确的技术.希望这可以节省您几个小时的比较,并帮助您在设计程序时做出更明智的决策.

  • 因此,如果原子属性不好,则它们是默认的.要增加样板代码? (2认同)

Dur*_*n.H 96

原子 =螺纹安全

非原子 =无线程安全

螺纹安全:

如果实例变量在从多个线程访问时表现正确,则它们是线程安全的,无论运行时环境是否调度或交错执行这些线程,并且调用代码没有额外的同步或其他协调.

在我们的背景下:

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

在哪里使用atomic:

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

含义atomic:

没有那么快,nonatomic因为nonatomic运行时不需要任何看门狗工作.

在哪里使用nonatomic:

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

  • 你在这里说的一切都是正确的,但对于今天的节目,最后一句基本上是"错误的",Dura.你真的很难以尝试以这种方式"提高性能".(我的意思是,在你进入光年之前,你会"不使用ARC","不使用NSString,因为它很慢!"等等.)举一个极端的例子,就像说"团队,不要在代码中添加任何注释,因为它会减慢我们的速度." 没有现实的开发流程,您可能希望在不可靠的情况下获得(不存在的)理论性能. (3认同)
  • @JoeBlow它是一个事实,你可以在这里验证它https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html (3认同)
  • Durai,FWIW,该[链接](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html)直接与您的“原子=线程安全”论点相矛盾。苹果在文档中明确表示:“属性原子性并不等同于对象的线程安全性。” 在实践中,原子性很少足以实现线程安全。 (2认同)

tip*_*low 69

我发现原子和非原子性的一个很好的解释放在这里.以下是相同的相关文字:

'原子'意味着它不能被分解.在OS /编程术语中,原子函数调用是一个不能被中断的函数 - 整个函数必须执行,并且不会被操作系统通常的上下文切换换出CPU直到它完成.以防你不知道:由于CPU一次只能做一件事,操作系统会在很短的时间内将CPU的访问权限转移到所有正在运行的进程,从而产生多任务处理的错觉.CPU调度程序可以(并且确实)在执行过程中的任何时刻中断进程 - 即使在函数调用中期也是如此.因此,对于更新共享计数器变量的操作,其中两个进程可以尝试同时更新变量,它们必须"原子地"执行,即每个更新操作必须完全完成才能将任何其他进程交换到中央处理器.

所以我猜测在这种情况下原子意味着属性读取器方法不能被中断 - 实际上意味着方法读取的变量不能在中途改变它们的值,因为其他一些线程/调用/函数得到了交换到CPU上.

因为atomic变量不能被中断,所以它们在任何一点所包含的值都是(线程锁定)保证不会被破坏,但是,确保这种线程锁定会使它们的访问速度变慢.non-atomic另一方面,变量没有这样的保证,但确实提供了更快捷的访问.总结一下,non-atomic当你知道你的变量不会被多个线程同时访问并加快速度时,请继续.


swi*_*Boy 66

阅读了这么多文章后,Stack Overflow发布并制作了演示应用程序以检查变量属性属性,我决定将所有属性信息放在一起:

  1. atomic //默认
  2. nonatomic
  3. strong = retain //默认
  4. weak = unsafe_unretained
  5. retain
  6. assign //默认
  7. unsafe_unretained
  8. copy
  9. readonly
  10. readwrite //默认

iOS中的变量属性属性或修饰符一文中,您可以找到所有上述属性,这肯定会对您有所帮助.

  1. atomic

    • atomic 表示只有一个线程访问变量(静态类型).
    • atomic 是线程安全的.
    • 但它的表现很慢
    • atomic 是默认行为
    • 非垃圾收集环境中的原子访问器(即使用retain/release/autorelease时)将使用锁来确保另一个线程不会干扰正确设置/获取值.
    • 它实际上不是关键字.

    例:

        @property (retain) NSString *name;
    
        @synthesize name;
    
    Run Code Online (Sandbox Code Playgroud)
  2. nonatomic

    • nonatomic 表示多线程访问变量(动态类型).
    • nonatomic 线程不安全.
    • 但它的性能很快
    • nonatomic不是默认行为.我们需要nonatomic在property属性中添加关键字.
    • 当两个不同的进程(线程)同时访问同一个变量时,它可能会导致意外行为.

    例:

        @property (nonatomic, retain) NSString *name;
    
        @synthesize name;
    
    Run Code Online (Sandbox Code Playgroud)


And*_*ant 54

原子:

原子保证访问属性将以原子方式执行.例如,它总是返回一个完全初始化的对象,一个线程上的任何属性的get/set必须在另一个线程访问它之前完成.

如果您想象同时在两个线程上发生以下函数,您可以看到为什么结果不会很漂亮.

-(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;
  }

  ...
}
Run Code Online (Sandbox Code Playgroud)

优点: 每次返回完全初始化的对象是多线程情况下的最佳选择.

缺点: 性能受到影响,使执行速度变慢

非原子:

与Atomic不同,它不能确保每次完全初始化对象返回.

优点: 执行速度极快.

缺点: 多线程情况下垃圾价值的可能性.

  • 这个评论没有多大意义.你能澄清一下吗?如果查看Apple站点上的示例,则atomic关键字会在更新其属性时同步对象. (5认同)

Jay*_*nor 52

最简单的回答:你的第二个例子没有区别.默认情况下,属性访问器是原子的.

非垃圾收集环境中的原子访问器(即使用retain/release/autorelease时)将使用锁来确保另一个线程不会干扰正确设置/获取值.

有关更多信息以及创建多线程应用程序时的其他注意事项,请参阅Apple的Objective-C 2.0文档的" 性能和线程 "部分.

  • 两个原因.首先,对于合成代码,它生成得更快(但不是线程安全代码).其次,如果您正在编写非原子的客户访问器,那么它允许您为任何未来用户注释代码在读取其接口时不是原子的,而不实现它们. (8认同)

IOS*_*cks 31

原子意味着只有一个线程访问变量(静态类型).Atomic是线程安全的,但它很慢.

Nonatomic意味着多个线程访问变量(动态类型).Nonatomic是线程不安全的,但速度很快.


小智 14

Atomic是线程安全的,它很并且很好地保证(不保证)无论有多少线程尝试通过同一区域访问,都只提供锁定值.使用atomic时,在此函数内部编写的一段代码将成为临界区的一部分,一次只能执行一个线程.

它只保证线程安全; 它并不保证.我的意思是你为你的汽车聘请专家司机,但它不能保证汽车不会发生事故.但是,概率仍然是最轻微的.

原子 - 它不能被分解,所以结果是预期的.使用非原子 - 当另一个线程访问内存区域时,它可以修改它,因此结果是意外的.

代码谈话:

Atomic使得属性线程的getter和setter安全.例如,如果你写了:

self.myProperty = value;
Run Code Online (Sandbox Code Playgroud)

是线程安全的.

[myArray addObject:@"Abc"] 
Run Code Online (Sandbox Code Playgroud)

不是线程安全的.


Dee*_*pak 13

没有这样的关键字"原子"

@property(atomic, retain) UITextField *userName;
Run Code Online (Sandbox Code Playgroud)

我们可以使用上面这样的

@property(retain) UITextField *userName;
Run Code Online (Sandbox Code Playgroud)

请参阅Stack Overflow 问题如果我使用@property(atomic,retain)NSString*myString,我会遇到问题.

  • "有这样的关键字",默认情况下不需要关键字,即使是默认值也不代表关键字不存在. (10认同)
  • 这是不正确的.关键字确实存在.这个答案具有误导性,我鼓励将其删除. (4认同)

Bin*_*ian 11

默认情况下atomic,这意味着它无论您何时使用属性花费你的表现,但它是线程安全的.Objective-C的作用是设置一个锁,只要实际的线程可以访问变量,只要执行setter/getter.

带有ivar _internal的属性的MRC示例:

[_internal lock]; //lock
id result = [[value retain] autorelease];
[_internal unlock];
return result;
Run Code Online (Sandbox Code Playgroud)

所以最后两个是相同的:

@property(atomic, retain) UITextField *userName;

@property(retain) UITextField *userName; // defaults to atomic
Run Code Online (Sandbox Code Playgroud)

另一方面,确实nonatomic没有为您的代码添加任何内容.因此,如果您自己编写安全机制,那么它只是线程安全的.

@property(nonatomic, retain) UITextField *userName;
Run Code Online (Sandbox Code Playgroud)

根本不必将关键字写为第一个属性属性.

不要忘记,这并不意味着整个属性是线程安全的.只有setter/getter的方法调用才是.但是如果你使用一个setter,然后使用2个不同的线程同时使用一个getter,那么它也可能被破坏!


Pro*_*ton 11

原子(默认)

默认为Atomic:如果您不键入任何内容,则属性是原子的.保证原子属性如果您尝试从中读取,则将返回有效值.它不会保证该值可能是什么,但是您将获得良好的数据,而不仅仅是垃圾内存.这允许您做的是,如果您有多个线程或多个进程指向单个变量,一个线程可以读取而另一个线程可以写入.如果它们同时命中,则读者线程保证获得两个值中的一个:在更改之前或在更改之后.什么原子能不给你任何关于你可能得到的那些价值的保证.原子通常与线程安全混淆,这是不正确的.您需要以其他方式保证您的线程安全.但是,原子将保证,如果你试图阅读,你会得到一些价值.

非原子

另一方面,正如你可能猜到的那样,非原子,只是意味着,"不要做那些原子的东西."你失去的是保证你总能得到回报.如果您尝试在写入过程中读取,则可以获取垃圾数据.但是,另一方面,你会更快一点.因为原子属性必须做一些魔术来保证你会得到一个值,它们会慢一些.如果它是您正在访问的属性,您可能需要下拉到非原子,以确保您不会产生速度惩罚.

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


小智 9

如果您在多线程代码中使用属性,那么您将能够看到非原子属性和原子属性之间的区别.非原子比原子快,原子是线程安全的,而不是非原子的.

Vijayendra Tripathi已经为多线程环境提供了一个例子.


Hon*_*ney 9

开始之前:您必须知道内存中的每个对象都需要从内存中释放出来才能使新编写器发生.你不能像在纸上那样简单地写一些东西.你必须首先擦除(dealloc)它,然后你可以写它.如果擦除完成(或完成一半)并且尚未编写任何内容(或写入一半)并且您尝试阅读它可能会非常有问题!原子和非原子帮助您以不同方式处理此问题.

首先阅读这个问题,然后阅读Bbum的答案.另外,然后阅读我的总结.


atomic 总是保证

  • 如果两个不同的人想要同时读写,那么你的论文就不会燃烧! - >即使在竞争条件下,您的应用程序也不会崩溃.
  • 如果一个人正在尝试写,并且只写了8个字母中的4个来写,那么中间没有可读,只有在写完所有8个字母时才能读取 - >不会读取(get) '仍在写入的线程',即如果要写入8个字节到字节,并且只写入4个字节 - 到那时,您将无法从中读取.但是因为我说它不会崩溃然后它会读取自动释放对象的值.
  • 如果写作之前已经删除了以前写在纸上然后有人想要阅读的内容,你仍然可以阅读.怎么样?你可以从类似的Mac OS垃圾桶的东西来读(如垃圾桶是不是仍然是100%,抹去......很明朗)--->如果ThreadA中是读而ThreadB已经释放来写,你可能会要么通过ThreadB从最终完全写入的值中获取值,要么从自动释放池中获取值.

保留计数是在Objective-C中管理内存的方式.创建对象时,它的保留计数为1.当您向对象发送保留消息时,其保留计数将增加1.当您向对象发送释放消息时,其保留计数将减1.当您向对象发送自动释放消息,其保留计数在将来的某个阶段递减1.如果对象的保留计数减少到0,则将其取消分配.

  • Atomic 保证线程安全,但它对实现线程安全很有用.线程安全性与您编写代码/正在读取/写入的线程队列的方式有关.它只保证不可崩溃的多线程.

什么?!多线程和线程安全性有何不同?

是.多线程意味着:多个线程可以同时读取共享数据,但我们不会崩溃,但它并不能保证您不会读取非自动释放的值.通过线程安全,可以保证您所读取的内容不会自动释放.我们默认情况下不会使所有内容成为原子的原因是,存在性能成本,并且对于大多数事情而言并不需要线程安全.我们的代码的一些部分需要它,对于那些少数部分,我们需要使用锁,互斥或同步以线程安全的方式编写代码.


nonatomic

  • 由于没有像Mac OS Trash Bin这样的东西,所以没有人关心你是否总是得到一个价值(< - 这可能会导致崩溃),也没有人关心是否有人试图在你的写作中途阅读(尽管写在记忆中的中途与写在纸上的中途非常不同,在记忆中它可以给你一个疯狂的愚蠢价值,而在纸面上你只能看到已写的一半) - >不保证不会崩溃,因为它不使用自动释放机制.
  • 不保证读取完整的书面价值!
  • 比原子快

总的来说,他们在两个方面有所不同

  • 是否因为拥有或不拥有自动释放池而崩溃.

  • 允许在"尚未完成的写入或空值"的中间读取,或者不允许并且仅在完全写入值时允许读取.


Sho*_*tta 9

  • -Atomic意味着只有一个线程访问变量(静态类型).
  • -Atomic是线程安全的.
  • - 但性能很慢

如何申报:

因为原子是默认的,所以

@property (retain) NSString *name;
Run Code Online (Sandbox Code Playgroud)

并在实现文件中

self.name = @"sourov";
Run Code Online (Sandbox Code Playgroud)

假设与三个属性相关的任务是

 @property (retain) NSString *name;
 @property (retain) NSString *A;
 @property (retain) NSString *B;
 self.name = @"sourov";
Run Code Online (Sandbox Code Playgroud)

所有属性并行工作(如异步).

如果从线程A中调用"name" ,

如果你打电话的话

[self setName:@"Datta"]
Run Code Online (Sandbox Code Playgroud)

来自主题B,

现在如果*name属性是非原子的那么

  • 它将为A返回值"Datta"
  • 它将为B返回值"Datta"

这就是为什么非原子被称为线程不安全但是由于并行执行它的性能很快

现在如果*name属性是原子的

  • 它将确保A的价值"Sourov"
  • 然后它将为B返回值"Datta"

这就是为什么原子被称为线程安全, 这就是为什么它被称为读写安全

这种情况操作将连续执行. 表现缓慢

- Nonatomic意味着多线程访问变量(动态类型).

- Nonatomic是线程不安全的.

- 但它的性能很快

-Nonatomic不是默认行为,我们需要在属性属性中添加非原子关键字.

对于In Swift确认Swift属性在ObjC意义上是非原子的.一个原因是你要考虑每个属性的原子性是否足以满足你的需求.

参考:https://forums.developer.apple.com/thread/25642

欲了解更多信息,请访问网站 http://rdcworld-iphone.blogspot.in/2012/12/variable-property-attributes-or.html

  • 正如许多其他人所说的那样,"原子"不是**线程安全的!它对线程问题更耐****,但不是线程安全的.它只是确保你获得一个完整的价值,即一个"正确的"价值(二进制水平),但绝不会确保它是你的业务逻辑的当前和"正确"值(它可能是过去的价值和你的逻辑无效). (4认同)

Sur*_*mas 9

原子性(默认)

Atomic 是默认值:如果您不输入任何内容,则您的属性是 atomic。原子属性保证,如果您尝试从中读取,您将获得一个有效值。它不保证该值可能是多少,但您将获得良好的数据,而不仅仅是垃圾内存。这允许您做的是,如果您有多个线程或多个进程指向一个变量,一个线程可以读取而另一个线程可以写入。如果它们同时命中,则保证读取器线程获得两个值之一:更改之前或更改之后。atomic 不能为您提供关于您可能获得哪些值的任何保证。Atomic 通常与线程安全混淆,这是不正确的。您需要以其他方式保证您的线程安全。

非原子的

另一方面,非原子的,正如你可能猜到的,只是意味着,“不要做那些原子的东西。” 你失去的是保证你总能得到一些东西。如果您尝试在写入过程中读取,您可能会取回垃圾数据。但是,另一方面,你走得更快一点。因为原子属性必须做一些魔法来保证你会得到一个值,所以它们有点慢。如果它是一个您经常访问的属性,您可能希望降到非原子属性,以确保您不会招致速度损失。使用权

礼貌https://academy.realm.io/posts/tmi-objective-c-property-attributes/

原子性属性属性(原子性和非原子性)并未反映在相应的 Swift 属性声明中,但是当从 Swift 访问导入的属性时,Objective-C 实现的原子性保证仍然有效。

所以?—?如果你在 Objective-C 中定义了一个原子属性,它在被 Swift 使用时将保持原子性。

礼貌 https://medium.com/@YogevSitton/atomic-vs-non-atomic-properties-crash-course-d11c23f4366c


Lax*_*hni 5

无论有多少线程正在执行getter和setter方法,atomic属性都确保保留完全初始化的值。

nonatomic属性指定合成的访问器仅直接设置或返回一个值,而不保证如果从不同的线程同时访问相同的值会发生什么情况。


归档时间:

查看次数:

473849 次

最近记录:

6 年,2 月 前