前言
atomic/nonatomic 是属性修饰符之一,atomic 代表原子性,nonatomic 代表非原子性;
原子性是防止方法调用到一半其它操作再次进入该方法,导致出现异常情况。
atomic 和 nonatomic 区别以及实现
首先我们知道 atomic 代表原子性,nonatomic 代表非原子性;用这两个修饰符来修饰属性,区别主要在于属性的 getter/setter 方法:atomic 会对 setter 方法进行加锁,nonatomic 不会对 setter 方法加锁。
atomic 修饰的属性,在 setter 方法中使用@synchronized加锁来确保原子操作,但是@synchronized相比于其它类型的锁,性能是最低效的,因为除了加锁之外,额外还会设置异常处理机制,性能消耗较大。这里就是为什么平时开发中很少使用 atomic 来修饰属性。
atomic 与 nonatomic 在 getter/setter 方法区别如下:
atomic 不保证线程安全
atomic 只会保证 setter/getter 方法是原子操作的,防止方法调用到一半其它操作再次进入该方法,导致出现异常情况。即原子性保证你访问的时候给你返回一个完好无损的对象,但是不会保证线程安全,这里有个经典的例子:
如果线程 A 调了 getter,与此同时线程 B 、线程 C 都调了 setter——那最后线程 A get 到的值,有3种可能:可能是 B、C set之前原始的值,也可能是 B set的值,也可能是 C set的值。同时,最终这个属性的值,可能是 B set的值,也有可能是 C set的值。所以atomic可并不能保证对象的线程安全。
这个问题其实包括两个块内存,一个是栈区指针的内存A,一个是堆区对象占用的内存B。
atomic 只是对属性的 getter/setter 方法加自旋锁,也就是对A加锁,这样可以保证A是线程安全的。这样并没有对B做任何处理,所以B不是线程安全的。
如果一个对象的改变不是直接调用 getter/setter 方法,而是直接对对象内部属性修改、字符串拼接、数组增加和移除元素等操作,就不能保证这个对象是线程安全的。
网友评论