本篇文章采用的源碼是objc4-781版本
使用atomic一定是線程安全的嗎?
atomic不是絕對的線程安全。atomic的本意是指屬性的存取方法是線程安全的,并不保證整個對象是線程安全的。
什么是線程不安全?
線程的不安全是由于多線程訪問和修改共享資源而引起的不可預測的結果(有可能crash)??梢院唵卫斫鉃槲覀兡玫降闹凳清e的。
首先了解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/getter方法都被加了spinlock自旋鎖。但是,需要注意的是spinlock已經由于存在優先級反轉問題被棄用并用os_unfair_lock替代。既然被棄用了,這里為什么還在用;原因是進入spinlock_t去看會發現,底層已經被os_unfair_lick替換:
光講代碼不易懂,來個例子
如果定義屬性NSInteger i是原子的,對i進行i = i + 1操作就是不安全的; 因為原子性只能保證讀寫安全,而該表達式需要三步操作:
1、讀取i的值存入寄存器;
2、將i加1;
3、修改i的值;
如果在第一步完成的時候,i被其他線程修改了,那么表達式執行的結果就與預期的不一樣,也就是不安全的。
上圖中我認為slice1,slice2打印應該是1到100
實際上