iOS atomic与nonatomic的区别以及各自功能

2019-08-06  本文已影响0人  尼古拉斯佩思

一、atomic与nonatomic的区别!

首先,先介绍一下atomicnonatomic
1.atomic使用同步锁,原子性:

在该属性在调用gettersetter方法时,会加上自旋锁(osspinlock)
即在属性在调用gettersetter方法时,保证同一时刻只能有一个线程调用属性的读/写方

2.nonatomic:不使用同步锁,非原子性:

在该属性在调用getter和setter方法时,不会加上自旋锁,也就是线程并不安全

然后,再介绍一下atomicnonatomic的申明方式
@property(nonatomic,strong) NSString *test;

@property (atomic,strong) NSString *test;

@property (strong) NSString *test;

代码中可以看到这样的书写方式,那么这三个代码有什么不同呢?

其实:

@property (atomic,strong) NSString *test;

@property (strong) NSString *test;

这两个代码完全是一样的结果,省略不写即默认为atomic,而不是nonatomic

中间,我为什么强调atomic属性申明时在调用gettersetter方法时会加上自旋锁(osspinlock)并且是只能有一个线程调用属性的读/写方法,没有说线程是安全的

对于atomic的属性,系统生成的 getter/setter会保证 get、set 操作的完整性,不受其他线程影响。
比如,线程 A 的 getter方法运行到一半,线程 B 调用了 setter:那么线程 A 的 getter还是能得到一个完好无损的对象。

如果有一个 atomic的属性 "name",如果线程 A 调[self setName:@"A"],线程 B 调[self setName:@"B"],线程 C 调[self name],那么所有这些不同线程上的操作都将依次顺序执行——也就是说,如果一个线程正在执行 getter/setter,其他线程就得等待。因此,属性 name是读/写安全的。

但是,如果有另一个线程 D 同时在调[name release],那可能就会crash,因为 release不受 getter/setter操作的限制。也就是说,这个属性只能说是读/写安全的,但并不是线程安全的,因为别的线程还能进行读写之外的其他操作。线程安全需要开发者自己来保证

最后为什么说nonatomic线程并不安全

如果 name属性是 nonatomic 的,那么上面例子里的所有线程 A、B、C、D 都可以同时执行,可能导致无法预料的结果。如果是atomic 的,那么 A、B、C 会串行,而 D 还是并行的。

其实苹果官方文档也有解释
还有自旋锁osspinlock因为并不安全已经被苹果淘汰,替换成为自旋锁os_unfair_lock,详情可以参考YY大神ibireme 不再安全的 OSSpinLock

以后的文章我会表述iOS锁的概念和的常见的几种锁

上一篇下一篇

猜你喜欢

热点阅读