本篇文章采用的源碼是objc4-781版本
使用atomic一定是線程安全的嗎?
atomic不是絕對(duì)的線程安全。atomic的本意是指屬性的存取方法是線程安全的稽坤,并不保證整個(gè)對(duì)象是線程安全的剩拢。
什么是線程不安全?
線程的不安全是由于多線程訪問(wèn)和修改共享資源而引起的不可預(yù)測(cè)的結(jié)果(有可能crash)够话±逗玻可以簡(jiǎn)單理解為我們拿到的值是錯(cuò)的。
首先了解atomic
的原子性和nonatomic
的非原子性
atomic :系統(tǒng)自動(dòng)生成的getter/setter方法會(huì)進(jìn)行加鎖操作女嘲;可以理解過(guò)讀寫(xiě)鎖畜份,可以保證讀寫(xiě)安全;較耗時(shí)欣尼。
nonatomic:系統(tǒng)自動(dòng)生成的getter/setter方法不會(huì)進(jìn)行加鎖操作爆雹;但速度會(huì)更快
源代碼分析atomic為什么不是線程安全
atomic只是對(duì)屬性的getter/setter方法進(jìn)行了加鎖操作,這種安全僅僅是get/set的讀寫(xiě)安全,僅此而已钙态,但是線程安全還有除了讀寫(xiě)的其他操作慧起,比如:當(dāng)一個(gè)線程正在get/set時(shí),另一個(gè)線程同時(shí)進(jìn)行release操作册倒,可能會(huì)直接crash蚓挤。
在runtime
時(shí)property
的atomic
是一個(gè)BOOL
值,是采用spinlock_t
鎖去實(shí)現(xiàn)的剩失;
你會(huì)發(fā)現(xiàn)atomic屬性的setter/getter方法都被加了spinlock自旋鎖屈尼。但是,需要注意的是spinlock已經(jīng)由于存在優(yōu)先級(jí)反轉(zhuǎn)問(wèn)題被棄用并用os_unfair_lock替代拴孤。既然被棄用了脾歧,這里為什么還在用;原因是進(jìn)入spinlock_t去看會(huì)發(fā)現(xiàn)演熟,底層已經(jīng)被os_unfair_lick替換:
光講代碼不易懂鞭执,來(lái)個(gè)例子
如果定義屬性NSInteger i是原子的,對(duì)i進(jìn)行i = i + 1操作就是不安全的芒粹; 因?yàn)樵有灾荒鼙WC讀寫(xiě)安全兄纺,而該表達(dá)式需要三步操作:
1、讀取i的值存入寄存器化漆;
2估脆、將i加1;
3座云、修改i的值疙赠;
如果在第一步完成的時(shí)候,i被其他線程修改了朦拖,那么表達(dá)式執(zhí)行的結(jié)果就與預(yù)期的不一樣圃阳,也就是不安全的。
上圖中我認(rèn)為slice1璧帝,slice2打印應(yīng)該是1到100
實(shí)際上