atomic与线程安全
本篇文章采用的源码是objc4-781版本
使用atomic一定是线程安全的吗?
atomic不是绝对的线程安全。atomic的本意是指属性的存取方法是线程安全的,并不保证整个对象是线程安全的。
什么是线程不安全?
线程的不安全是由于多线程访问和修改共享资源而引起的不可预测的结果(有可能crash)。可以简单理解为我们拿到的值是错的。
首先了解atomic
的原子性和nonatomic
的非原子性
atomic :系统自动生成的getter/setter方法会进行加锁操作;可以理解过读写锁,可以保证读写安全;较耗时。
nonatomic:系统自动生成的getter/setter方法不会进行加锁操作;但速度会更快
源代码分析atomic为什么不是线程安全
atomic只是对属性的getter/setter方法进行了加锁操作,这种安全仅仅是get/set的读写安全,仅此而已,但是线程安全还有除了读写的其他操作,比如:当一个线程正在get/set时,另一个线程同时进行release操作,可能会直接crash。
在runtime
时property
的atomic
是一个BOOL
值,是采用spinlock_t
锁去实现的;
atomic setter
你会发现atomic属性的setter/getter方法都被加了spinlock自旋锁。但是,需要注意的是spinlock已经由于存在优先级反转问题被弃用并用os_unfair_lock替代。既然被弃用了,这里为什么还在用;原因是进入spinlock_t去看会发现,底层已经被os_unfair_lick替换:
spinlock_t
光讲代码不易懂,来个例子
如果定义属性NSInteger i是原子的,对i进行i = i + 1操作就是不安全的; 因为原子性只能保证读写安全,而该表达式需要三步操作:
1、读取i的值存入寄存器;
2、将i加1;
3、修改i的值;
如果在第一步完成的时候,i被其他线程修改了,那么表达式执行的结果就与预期的不一样,也就是不安全的。
上图中我认为slice1,slice2打印应该是1到100
实际上