為什么不常用atomic硅蹦?
我們?cè)陂_發(fā)中修飾屬性一般用的是nonatomic而不是atomic,這是因?yàn)閍tomic比較耗性能裤翩。
有人說使用atomic更安全芥炭,那為什么不使用atomic呢?
atomic是用于保證屬性setter羽峰、getter的原子性操作
什么叫保證屬性setter趟咆、getter的原子性操作呢?我們知道在某個(gè)類使用property修飾屬性后梅屉,系統(tǒng)會(huì)自動(dòng)為我們生成setter方法和getter方法的聲明和實(shí)現(xiàn)以及帶有下劃線的成員變量(在分類中只能生成setter值纱、getter方法的聲明),保證這兩個(gè)方法的原子性操作就相當(dāng)于在兩個(gè)方法內(nèi)加了線程同步鎖坯汤。它能保證讀虐唠、寫同一時(shí)間只能進(jìn)行其中的一項(xiàng)操作,要么是讀惰聂,要么是寫疆偿。但這并不能保證線程的安全。
atomic使用場(chǎng)景
此時(shí)的animal需要使用atomic進(jìn)行修飾搓幌,否者會(huì)出現(xiàn)EXC_BAC_INSTRUCTION的錯(cuò)誤杆故,這是因?yàn)槎嗑€程操作的時(shí)候某個(gè)線程訪問了已經(jīng)釋放的內(nèi)存。
atomic并不能保證線程的安全
atomic相當(dāng)于是在setter溉愁、getter方法內(nèi)部進(jìn)行加鎖处铛,但多線程在外面同時(shí)調(diào)用setter、getter方法就不能保證線程的安全了。如果想要保證線程安全撤蟆,我們還是需要在外部進(jìn)行加鎖篙贸。
干巴巴的文字可能不是很好理解,我們通過代碼舉個(gè)例子枫疆。
看代碼
MJPerson *p = [[MJPerson alloc] init];
p.data = [NSMutableArray array];
NSMutableArray *array = p.data;
// 加鎖
[array addObject:@"1"];
[array addObject:@"2"];
[array addObject:@"3"];
// 解鎖
其中的data是MJPerson實(shí)例的一個(gè)屬性爵川,在首次被賦值的時(shí)候它是安全的,沒問題息楔,但后面往這個(gè)可變數(shù)組的屬性中添加數(shù)據(jù)就會(huì)出現(xiàn)問題寝贡,如果是多個(gè)線程同時(shí)執(zhí)行,它就不能保證1值依、2圃泡、3按照順序被添加到數(shù)組中了,所以還需要在外面進(jìn)行加鎖愿险。
另一個(gè)例子:
一個(gè)Person類有兩個(gè)屬性“姓”颇蜡、“名”,兩個(gè)線程同時(shí)給“姓”和“名”賦值辆亏,假設(shè)線程A準(zhǔn)備賦值的分別是“張”风秤、“三”, 線程B準(zhǔn)備賦值的分別是“李”扮叨、“四”缤弦,由于賦值的操作沒有加鎖,那么賦值后的結(jié)果可能會(huì)出現(xiàn)person的姓名是“張四”和“李三”的情況彻磁。
附加(默認(rèn)修飾符)
1.基本數(shù)據(jù)類型:atomic readwrite assign
2.普通OC對(duì)象: atomic readwrite strong