好的文章:
一寇仓、內(nèi)存管理機(jī)制
二、atomic 和nonatomic的區(qū)別(性能器联、加鎖)
strong :強(qiáng)引用二汛,ARC中使用,與MRC中retain類似主籍,使用之后习贫,計(jì)數(shù)器+1。
weak :弱引用 千元,ARC中使用苫昌,如果只想的對(duì)象被釋放了,其指向nil幸海,可以有效的避免野指針祟身,其引用計(jì)數(shù)為1奥务。
readwrite : 可讀可寫特性,需要生成getter方法和setter方法時(shí)使用袜硫。
readonly : 只讀特性氯葬,只會(huì)生成getter方法 不會(huì)生成setter方法,不希望屬性在類外改變婉陷。
assign :賦值特性帚称,不涉及引用計(jì)數(shù),弱引用秽澳,setter方法將傳入?yún)?shù)賦值給實(shí)例變量闯睹,僅設(shè)置變量時(shí)使用。
retain :表示持有特性担神,setter方法將傳入?yún)?shù)先保留楼吃,再賦值,傳入?yún)?shù)的retaincount會(huì)+1妄讯。
copy :表示拷貝特性孩锡,setter方法將傳入對(duì)象復(fù)制一份,需要完全一份新的變量時(shí)亥贸。
nonatomic :非原子操作躬窜,不加同步,多線程訪問可提高性能砌函,但是線程不安全的斩披。決定編譯器生成的setter getter是否是原子操作。
atomic :原子操作讹俊,同步的垦沉,表示多線程安全,與nonatomic相反仍劈。
注意:
1厕倍、atomic關(guān)鍵字修飾屬性的性能要比nonatomic關(guān)鍵字修飾屬性的性能要低。所以通常在iOS開發(fā)中贩疙,定義屬性使用nonatomic讹弯。目的就是為了提高性能,節(jié)省可憐的資源这溅。
2组民、為什么atomic關(guān)鍵字修飾的屬性性能會(huì)低呢?
因?yàn)閍tomic底層有加鎖的操作悲靴,無論是什么鎖內(nèi)存都會(huì)有一定的開銷臭胜,性能肯定會(huì)比nonatomic低。
當(dāng)定義一個(gè)屬性之后,編譯器會(huì)為自動(dòng)為我們生成帶_(下劃線)的成員變量以及getter/setter方法耸三, 如果使用atomic修飾屬性乱陡,那么在編譯器為我們生成setter/getter方法的時(shí)候,會(huì)做加鎖的操作仪壮,加鎖的目的就是為了保證存取值的安全性/完整性憨颠。看場(chǎng)景一
場(chǎng)景一:A線程积锅、B線程
如果使用atomic修飾屬性值爽彤,有A和B兩個(gè)線程,A線程對(duì)屬性進(jìn)行賦值乏沸,當(dāng)A線程賦值進(jìn)行一半的時(shí)候淫茵,由于加鎖的緣故,A線程會(huì)持有這把鎖蹬跃,當(dāng)B線程進(jìn)行取值操作時(shí)候,發(fā)現(xiàn)A線程持有鎖铆铆,那么會(huì)進(jìn)行等待蝶缀,當(dāng)A線程賦值操作結(jié)束后,會(huì)放開鎖薄货,那么B線程持有這把鎖翁都,所以可以保證B線程一定可以取到一個(gè)完整的值。
如果使用nonatomic修飾屬性值谅猾,有A和B兩個(gè)線程柄慰,A線程對(duì)屬性進(jìn)行賦值,當(dāng)A線程賦值進(jìn)行一半的時(shí)候税娜,B線程進(jìn)行取值操作坐搔,由于沒有加鎖,B線程取不到一個(gè)完整的值敬矩,拿到一個(gè)不完整的值去做一些操作就可能會(huì)發(fā)生意想不到的事情概行。
但是atomic并不能保證線程是安全的,看場(chǎng)景二
場(chǎng)景二:A線程弧岳、B線程凳忙、C線程
使用atomic修飾屬性,如果有A禽炬、B和C三個(gè)線程涧卵。其中A和B線程同時(shí)對(duì)一個(gè)屬性進(jìn)行賦值操作,當(dāng)賦值一半的時(shí)候腹尖,C線程進(jìn)行取值操作柳恐,那么可以保證C線程一定可以取到一個(gè)完整的值,但是這個(gè)值的內(nèi)容可能是A線程賦的值,也可能是B線程賦的值胎撤,也可能是原始值晓殊,雖然取得了完整的值,但是這個(gè)值不一定是程序員想要的伤提,所以說atomic并不是線程安全的巫俺。
總結(jié):在平時(shí)開發(fā)的時(shí)候,不涉及線程安全的時(shí)候肿男,比如一些UI控件必須在主線程操作的介汹,用nonatomic可以提高性能。而真正要涉及線程安全舶沛,不能只靠編譯器嘹承,需要程序員自己控制。
僵尸對(duì)象如庭、野指針與空指針
1叹卷、僵尸對(duì)象: 所占用的內(nèi)存已經(jīng)被回收的對(duì)象叫僵尸對(duì)象,
注意:僵尸對(duì)象不能再使用
2坪它、野指針: 指向僵尸對(duì)象的指針叫野指針
注意:給野指針發(fā)送消息會(huì)報(bào)錯(cuò)EXC_BAD_ACCESS錯(cuò)誤:訪問了一塊已經(jīng)被回收的內(nèi)存
3骤竹、空指針: 沒有指向任何對(duì)象的指針(存儲(chǔ)的東西是nil,NULL,0)。
注意:給空指針發(fā)送消息不會(huì)報(bào)錯(cuò),系統(tǒng)什么也不會(huì)做,所以在對(duì)象被釋放時(shí)將指針設(shè)置為nil可以避免野指針錯(cuò)誤
注: 默認(rèn)情況下,Xcode是不會(huì)監(jiān)聽僵尸對(duì)象的,所以需要我們自己手動(dòng)開啟,開啟監(jiān)聽僵尸對(duì)象步驟為: Edit Scheme ->; Run ->; Diagnostics ->; Objective-C的Enable Zombie Objects打鉤,這樣便可以在因?yàn)榻┦瑢?duì)象報(bào)錯(cuò)的時(shí)候給出更多錯(cuò)誤信息