實(shí)現(xiàn)同步機(jī)制目前知道有3中方法,分別是@synchronized嗓袱、NSLock、GCD索抓。
@synchronized
@synchronized:它會(huì)根據(jù)指定的對(duì)象毯炮,自動(dòng)創(chuàng)建一個(gè)鎖,并等待塊中的代碼執(zhí)行完畢桃煎,鎖就釋放了。
- (NSString *)someString {
@synchronized(self) {
return _someString;
}
}
- (void)setSomeString:(NSString *)someString {
@synchronized(self) {
_someString = someString;
}
}
缺點(diǎn):濫用@synchronized會(huì)危險(xiǎn)为迈,因?yàn)樗型綁K都會(huì)彼此搶奪一個(gè)鎖,要是很多個(gè)屬性能這么寫(xiě)的話葫辐,那么每個(gè)屬性的同步塊都要等其他所有同步塊執(zhí)行完畢才能執(zhí)行,這會(huì)大大降低代碼的執(zhí)行效率耿战。
NSLock
_lock = [[NSLock alloc] init];
- (void)sychronizedMethod {
[_lock lock];
//Safe
[_lock unlock];
}
缺點(diǎn):極端情況下焊傅,同步塊會(huì)導(dǎo)致死鎖剂陡。而且NSLock效率也不是很高狐胎。
GCD
它能以更簡(jiǎn)單鸭栖,更高效的形式為代碼加鎖握巢。
1.使用串行同步隊(duì)列來(lái)代替同步塊或鎖對(duì)象
_syncQueue = dispatch_queue_create("com.effectiveobject.syncQueue", NULL);
- (NSString)someString {
__block NSString *localSomeString;
dispatch_sync(_syncQueue, ^{
localSomeString = _someString;
});
return localSomeString;
}
- (void)setSomeString:(NSString *)someString {
dispatch_sync(_syncQueue, ^{
_someString = someString;
})
}
我們都知道,串行同步隊(duì)列即任務(wù)按順序執(zhí)行暴浦,并且不回開(kāi)辟新的線程,使讀取操作與寫(xiě)入操作都安排在同一個(gè)隊(duì)列里肉渴,即可保證數(shù)據(jù)同步带射。
2.使用串行異步隊(duì)列來(lái)代替同步塊或鎖對(duì)象
_syncQueue = dispatch_queue_create("com.effectiveobject.syncQueue", NULL);
- (NSString)someString {
__block NSString *localSomeString;
dispatch_sync(_syncQueue, ^{
localSomeString = _someString;
});
return localSomeString;
}
- (void)setSomeString:(NSString *)someString {
dispatch_async(_syncQueue, ^{
_someString = someString;
})
}
這是把設(shè)置方法改成了異步。因?yàn)槭谴嘘?duì)列窟社,讀取操作與寫(xiě)入操作依然會(huì)按順序執(zhí)行。
3.并發(fā)隊(duì)列+dispatch_barrier_async
_syncQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- (NSString)someString {
__block NSString *localSomeString;
dispatch_sync(_syncQueue, ^{
localSomeString = _someString;
});
return localSomeString;
}
- (void)setSomeString:(NSString *)someString {
dispatch_barrier_async(_syncQueue, ^{
_someString = someString;
})
}
dispatch_barrier_async
能夠使之前加入并發(fā)隊(duì)列的塊先執(zhí)行完灿里,再單獨(dú)執(zhí)行柵欄塊,待柵欄塊執(zhí)行過(guò)后匣吊,再按正常方式向下處理寸潦。
本例中,使用柵欄塊來(lái)實(shí)現(xiàn)屬性的設(shè)置方法见转,來(lái)保證讀取操作可以并發(fā)執(zhí)行,但是寫(xiě)入操作是單獨(dú)執(zhí)行的蒜哀。