现在的位置: 首页 > 综合 > 正文

nonatomic atomic 属性声明的作用(以 附带 retain关键字举例)iOS开发

2018年05月26日 ⁄ 综合 ⁄ 共 3529字 ⁄ 字号 评论关闭

转载说明(谢谢)

http://blog.csdn.net/a21064346/article/details/8086701

点击打开链接

昨天写了一个 关于 atomic 原子操作的文章,想起刚学ios开发时一直没有弄明白的问题 

nonatomic

@property (nonatomic,retain)NSString *name;

为什么要这样来声明 成员变量 name?

可能有一些人对这个也不是很清楚,一直都是带点模糊的感觉。那么我就把我的理解 分享给大家。


首先,atomic,nonatomic 是一对反义词。前者使用 原子性,后者不使用 原子性。关于原子操作,可以看我写过的一个blog来理解

这里是地址:

http://blog.csdn.net/a21064346/article/details/8076972


atomic 是属性声明关键字中默认的一个属性,如果你没有对 原子性进行一个声明(atomic or nonatomic),那么系统会默认你选择的是atomic。

atomic 声明属性的成员变量,它没有一个内存“加锁”的概念,而是一个寄存器“加锁(这里其实就是一个防死锁,不让别人继续访问正在改变的value)”的概念(getter为最新从cpu返回来的数值),保证每次都是寄存器中计算好的数据,而不是返回到内存中已经不用计算的数据。他保证的是,cpu中只有一个方法,能访问到这一个变量,并且能够readAndWrite我认为,它会从cpu中取最新的value,即
声明成员变量的 最新value。取得的数据,可能是从内存中第一次调用后的,也可能是cpu中第二次或者第n次正在处理的数据。


nonatomic则是直接从内存中取数值,因为它是从内存中取得数据,它并没有一个加锁的保护来用于cpu中的寄存器计算Value,它只是单纯的从内存地址中,当前的内存存储的数据结果来进行使用。所以在多线程中,我们应该对这样的变量进行nonatomic声明,因为它一直都能响应getter方法,防止你数据取到一半,结果数据释放了,或者数据
还在其他线程中正在写入。这就避免了 取到的数据不是你预期的那一个(尽管这一个并不是 另外一个线程正在修改的数据)。


结合下面一段代码来进行理解:

name setter方法:(重写)

[csharp] view
plain
copy

  1. -(void) setName:(NSString*)string  
  2. {  
  3.   if (name)  
  4.   {  
  5.     [name release];   
  6.     // what happens if the second thread jumps in now !?  
  7.     // name may be deleted, but our 'name' variable is still set!  
  8.     name = nil;  
  9.   }  
  10.   name = [string retain];  
  11.   ...  
  12. }  

如果name声明在 class A中,class B 和 class C来负责 取用。

我们假设有 3个线程同时 访问到了A中的 name 。线程1:我正在给我的class A name 一个新的value。线程2:class B 要从A 得到当前的name。线程3:class C 要从A得到当前的name。而name声明时,没有加non atomic的关键字。那么,B 和 C 取道的数值可能会 不一样。可能是nil,也可能是 string,也可能是最初始的那一个value。这是不 安全的



这里是 一个app的文档。我在一些地方标注了红色,方便大家理解。


Properties Are Atomic by Default

By default, an Objective-C property is atomic. This means that the synthesized accessors ensure that a value is always fully
retrieved by the getter method or fully set via the setter method, even if the accessors are called simultaneously from different threads.

Because the internal implementation and synchronization of atomic accessor methods is private, it’s not possible to combine a synthesized accessor with an accessor method that you implement yourself. You’ll get a compiler warning if you try, for example, to
provide a custom setter for an atomic readwrite property but leave the compiler to synthesize the getter.

You can use the nonatomic property attribute to specify that synthesized accessors simply set or return a value directly, with no guarantees about what
happens if that same value is accessed simultaneously from different threads. For this reason, it’s faster to access a nonatomic property than an atomic one, and it’s fine to combine a synthesized setter, for example, with your own getter implementation:

这段话,说明了nonatomic的faster的原因,因为它是直接访问 内存的地址。它不需要去关心 其他线程如何去改变这个数值,并且中间没有死锁的保护,没有其他线程中如何等待cpu用完它得到最新的value,然后接着更改,它只需直接从内存中访问到当前内存地址中的能用到的数据即可(也可以理解为,getter方法一直都能返回数值,尽管折个数值在cpu中改变着)。

@interface XYZObject : NSObject
@property (nonatomic) NSObject *nonatomicObject;
@end
@implementation XYZObject
- (NSObject *)nonatomicObject {
    return _nonatomicObject;
}
// setter will be synthesized automatically
@end

Note: Property atomicity is not synonymous with an object’s thread
safety
.

Consider an XYZPerson object in which both a person’s first and last names are changed using atomic accessors from one thread. If another thread accesses
both names at the same time, the atomic getter methods will return complete strings (without crashing), but there’s no guarantee that those values will be the right names relative to each other. If the first name is accessed before the change, but the last
name is accessed after the change, you’ll end up with an inconsistent, mismatched pair of names.

This example is quite simple, but the problem of thread safety becomes much more complex when considered across a network of related objects. Thread safety is covered in more detail in Concurrency
Programming Guide
.

上面一段话是 说明 atomicity的 不安全性。因为 atomic 不保证 当前数据 是否会在其他线程中数据安全,没有一个互斥的保护,只是一个死锁的保护。大家都可以访问当前cpu中(寄存器中)正在改变的value。

抱歉!评论已关闭.