摘抄蘋果官方文檔為
Atomic is the default: if you don’t type anything, your property is atomic. An atomic property is guaranteed that if you try to read from it, you will get back a valid value. It does not make any guarantees about what that value might be, but you will get back good data, not just junk memory. What this allows you to do is if you have multiple threads or multiple processes pointing at a single variable, one thread can read and another thread can write. If they hit at the same time, the reader thread is guaranteed to get one of the two values: either before the change or after the change. What atomic does not give you is any sort of guarantee about which of those values you might get. Atomic is really commonly confused with being thread-safe, and that is not correct. You need to guarantee your thread safety other ways. However, atomic will guarantee that if you try to read, you get back some kind of value.
nonatomic
On the flip side, non-atomic, as you can probably guess, just means, “don’t do that atomic stuff.” What you lose is that guarantee that you always get back something. If you try to read in the middle of a write, you could get back garbage data. But, on the other hand, you go a little bit faster. Because atomic properties have to do some magic to guarantee that you will get back a value, they are a bit slower. If it is a property that you are accessing a lot, you may want to drop down to nonatomic to make sure that you are not incurring that speed penalty.
設(shè)置成員變量的@property屬性時(shí)派撕,默認(rèn)為atomic蚁孔,提供多線程安全。
在多線程環(huán)境下碾阁,原子操作是必要的,否則有可能引起錯(cuò)誤的結(jié)果些楣。加了atomic脂凶,setter函數(shù)會(huì)變成下面這樣:
{lock}
if (property != newValue) {
[property release];
property = [newValue retain];
}
{unlock}
也就說使用了atomic屬性內(nèi)部會(huì)通過加鎖的機(jī)制來確保其get/set操作的準(zhǔn)確性,防止在寫為完成的時(shí)候被另一個(gè)線程讀取愁茁,造成數(shù)據(jù)錯(cuò)誤蚕钦,缺點(diǎn)也是明顯的在ios中加鎖是一個(gè)很消耗系統(tǒng)資源的操作。
所以我們使用的屬性大部分為nonatomic鹅很,原因就是使用atomic開銷比較大嘶居,帶來性能問題,而且使用atomic也不能保證對象多線程的安全促煮,它只是只能保證你訪問的時(shí)候給你返回一個(gè)完好無損的值而已邮屁。
例如:假設(shè)有一個(gè) atomic 的屬性 "name",如果線程 A 調(diào)[self setName:@"A"]菠齿,線程 B 調(diào)[self setName:@"B"]佑吝,線程 C 調(diào)[self name],那么所有這些不同線程上的操作都將依次順序執(zhí)行——也就是說绳匀,如果一個(gè)線程正在執(zhí)行 getter/setter芋忿,其他線程就得等待炸客。因此,屬性 name 是讀/寫安全的戈钢。
但是痹仙,如果有另一個(gè)線程 D 同時(shí)在調(diào)[name release],那可能就會(huì)crash逆趣,因?yàn)?release 不受 getter/setter 操作的限制蝶溶。也就是說,這個(gè)屬性只能說是讀/寫安全的宣渗,但并不是線程安全的抖所,因?yàn)閯e的線程還能進(jìn)行讀寫之外的其他操作。線程安全需要開發(fā)者自己來保證痕囱。
如果 name 屬性是 nonatomic 的田轧,那么上面例子里的所有線程 A、B鞍恢、C傻粘、D 都可以同時(shí)執(zhí)行,可能導(dǎo)致無法預(yù)料的結(jié)果帮掉。如果是 atomic 的弦悉,那么 A、B蟆炊、C 會(huì)串行稽莉,而 D 還是并行的。
我們可以認(rèn)為atomic只對一個(gè)屬性的getter/setter是安全的涩搓,其它的線程安全是無法保證的污秆。
現(xiàn)在總結(jié)一下nonatomic與atomic的區(qū)別:
atomic:
系統(tǒng)默認(rèn)
會(huì)保證 CPU 能在別的線程來訪問這個(gè)屬性之前,先執(zhí)行完當(dāng)前流程
性能低昧甘,速度慢
atomic 對象的getter/setter方法實(shí)現(xiàn):
-
(void)setCurrentImage:(UIImage *)currentImage
{
@synchronized(self) {
if (_currentImage != currentImage) {
[_currentImage release];
_currentImage = [currentImage retain];}
}
} (UIImage *)currentImage
{
@synchronized(self) {
return _currentImage;
}
}
nonatomic:
不是默認(rèn)的
速度快
線程不安全的
nonatomic 對象的getter/setter方法實(shí)現(xiàn):-
(void)setCurrentImage:(UIImage *)currentImage
{
if (_currentImage != currentImage) {
[_currentImage release];
_currentImage = [currentImage retain];}
} (UIImage *)currentImage
{
return _currentImage;
}