nonatomic:不安全
atomic:加鎖+耗性能
只知道這兩個(gè)特點(diǎn)是不夠的,下面根據(jù)代碼分析原因。
//有兩個(gè)屬性张漂,分別設(shè)置為nonatomic和atomic
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (nonatomic, strong) NSString *name;
@property (atomic, assign) int number;
@end
一晴玖、 10000個(gè)異步任務(wù)读存,修改name屬性的值
- (void)nonatomic{
for (NSInteger i = 0; i < 10000; i++) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
self.name = [NSString stringWithFormat:@"name:%ld", i];
});
}
}
執(zhí)行結(jié)果:崩潰,崩潰原因是在子線程Thread8上呕屎,對(duì)象釋放了让簿。
image.png
結(jié)果分析:
1、在MRC模式下秀睛,屬性name的set方法如下:
-(void)setName:(NSString *)name{
if (_name != name) {
[_name release];
[name retain];
_name = name;
}
}
2尔当、雖然在ARC模式下不用寫其set方法,但是在底層還是會(huì)走到這里
3蹂安、因?yàn)槭嵌嗑€程椭迎,且沒有加鎖保護(hù),所以在一個(gè)線程走到[_name release]后田盈,可能在另一個(gè)線程又一次去釋放畜号,這時(shí)候造成崩潰。
4允瞧、把name屬性的nonatomic改成atomic就不會(huì)崩潰了简软,因?yàn)閍tomic加鎖了蛮拔,是安全的。
二替饿、接著上步說用atomic就安全了语泽,再進(jìn)一步分析
number屬性使用atomic修飾的
- (void)atomic{
_number = 0;
dispatch_apply(10000, dispatch_get_global_queue(0, 0), ^(size_t index) {
self->_number ++;
});
NSLog(@"_number:%d", _number);
}
執(zhí)行結(jié)果:執(zhí)行結(jié)果并不是10000,而且每次運(yùn)行結(jié)果都不一樣视卢,即運(yùn)行結(jié)果不可預(yù)見踱卵。
image.png
結(jié)果分析:
_number++等價(jià)于
int temp = _number+1;
_number = temp;
雖然atomic保證了number屬性線程安全了,但是并不能保證temp變量的線程安全据过,又因?yàn)槭嵌嗑€程的惋砂,所以有可能同時(shí)執(zhí)行多次 int temp = _number+1;才執(zhí)行一次 _number = temp;導(dǎo)致結(jié)果每次都不同,而且結(jié)果不可預(yù)知绳锅。