Nsmutablearray線程安全

數(shù)組線程安全的思考NSMutableArray是線程不安全的,當有多個線程同時對數(shù)組進行操作的時候可能導致崩潰或數(shù)據(jù)錯誤汉操,下面是我對線程安全的幾個思路再来,希望由此能給你帶來一些思路,如果有錯誤的地方還希望大家能夠指出

1.對數(shù)組的讀寫都加鎖磷瘤,雖然數(shù)組是線程安全了芒篷,但失去了多線程的優(yōu)勢

2.然后又想可以只對寫操作加鎖然后定義一個全局變量來表示現(xiàn)在有沒有寫操作搜变,如果有寫操作就等寫完了在讀,那么問題來了如果一個線程先讀取數(shù)據(jù)緊接著一個線程對數(shù)組寫的操作梭伐,讀的時候還沒有加鎖同樣會導致崩潰或數(shù)據(jù)錯誤痹雅,這個方案pass掉

3.第三種方案說之前先介紹一下dispatch_barrier_async,dispatch_barrier_async 追加到 queue 中后糊识,會等待 queue 中的任務都結束后绩社,再執(zhí)行 dispatch_barrier_async 的任務,等 dispatch_barrier_async 的任務結束后赂苗,才恢復任務執(zhí)行愉耙, 用dispatch_async和dispatch_barrier_async結合保證NSMutableArray的線程安全,用dispatch_async讀和dispatch_barrier_async寫(add,remove,replace)拌滋,當有任務在讀的時候寫操作會等到所有的讀操作都結束了才會寫朴沿,同樣當有寫任務時,讀任務會等寫操作完了才會讀败砂,既保證了線程安全又發(fā)揮了多線程的優(yōu)勢赌渣,但還是有個不足,當我們重寫讀的方法時dispatch_async是另開辟線程去執(zhí)行的而且是立馬返回的昌犹,所以我們不能拿到執(zhí)行結果坚芜,需要去另寫一個方法來返回讀的結果,但是我們又不想改變調(diào)用者的習慣于是又想到了一下方案

4.用dispatch_sync和dispatch_barrier_async結合保證NSMutableArray的線程安全斜姥,dispatch_sync是在當前線程上執(zhí)行不會另開辟新的線程鸿竖,當線程返回的時候就可以拿到讀取的結果,我認為這個方案是最完美的選擇铸敏,既保證的線程安全有發(fā)揮了多線程的優(yōu)勢還不用另寫方法返回結果缚忧,完美~數(shù)組線程安全的實現(xiàn)下面咱們來看一下NSMutableArray線程安全的實現(xiàn)1 繼承 NSMutableArray創(chuàng)建NSKSafeMutableArray在這個地方遇到了一些坑通過查閱文檔發(fā)現(xiàn)問題所在:在 Cocoa 中有一種奇葩的類存在 Class Clusters。面向對象的編程告訴我們:“類可以繼承杈笔,子類具有父類的方法”闪水。而 Cocoa 中的 Class Clusters 雖然平時表現(xiàn)的像普通類一樣,但子類卻沒法繼承父類的方法蒙具。 NSMutableArray就是這樣的存在敦第。為什么會這樣呢?因為 Class Clusters 內(nèi)部其實是由多個私有的類和方法組成店量。雖然它有這樣的弊端,但是好處還是不言而喻的鞠呈。例如融师,NSNumber 其實也是這種類,這樣一個類可以把各種不同的原始類型封裝到一個類下面蚁吝,提供統(tǒng)一的接口旱爆。這正設計模式中的抽象工廠模式舀射。查看Apple的文檔,要繼承這樣的類需要必須實現(xiàn)其primitive methods方法怀伦,實現(xiàn)了這些方法脆烟,其它方法便都能通過這些方法組合而成。

比如需要繼承NSMutableArray就需要實現(xiàn)它的以下primitive methods:

- (void)addObject:(id)anObject;

- (void)insertObject:(id)anObject atIndex:(NSUInteger)index;

- (void)removeLastObject;

- (void)removeObjectAtIndex:(NSUInteger)index;

- (void)replaceObjectAtIndex:(NSUInteger)index withObject(id)anObject;

NSArray的primitive methods:

- (NSUInteger)count;- (id)objectAtIndex:(NSUInteger)index;

# NSKSafeMutableArray.h 的實現(xiàn)如下

#import "NSKSafeMutableArray.h"

@interface NSKSafeMutableArray(){? ? CFMutableArrayRef _array;}

@end

@implementation NSKSafeMutableArray

- (id)init{

return [self initWithCapacity:10];

}

- (id)initWithCapacity:(NSUInteger)numItems{

self = [super init];

if (self)? ? {

_array = CFArrayCreateMutable(kCFAllocatorDefault, numItems,? &kCFTypeArrayCallBacks);

}

return self;

}

- (NSUInteger)count {

__block NSUInteger result;

dispatch_sync(self.syncQueue, ^{? ? ? ? result = CFArrayGetCount(_array);? ? });? ? return result;

}

- (id)objectAtIndex:(NSUInteger)index {? ? __block id result;? ? dispatch_sync(self.syncQueue, ^{? ? ? ? NSUInteger count = CFArrayGetCount(_array);? ? ? ? result = indexcount) {

blockindex = count;

}

CFArrayInsertValueAtIndex(_array, index, (__bridge const void *)anObject);

});

}

- (void)removeObjectAtIndex:(NSUInteger)index

{

dispatch_barrier_async(self.syncQueue, ^{

NSUInteger count = CFArrayGetCount(_array);

NSLog(@"count:%lu,index:%lu",(unsigned long)count,(unsigned long)index);

if (index < count) {

CFArrayRemoveValueAtIndex(_array, index);

}

});

}

- (void)addObject:(id)anObject

{

dispatch_barrier_async(self.syncQueue, ^{

if (!anObject)

return;

CFArrayAppendValue(_array, (__bridge const void *)anObject);

});

}

- (void)removeLastObject {

dispatch_barrier_async(self.syncQueue, ^{

NSUInteger count = CFArrayGetCount(_array);

if (count > 0) {

CFArrayRemoveValueAtIndex(_array, count-1);

}

});

}

- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject {

dispatch_barrier_async(self.syncQueue, ^{

if (!anObject)

return;

NSUInteger count = CFArrayGetCount(_array);

CFArraySetValueAtIndex(_array, index, (__bridge const void*)anObject);

});

}

#pragma mark Optional

- (void)removeAllObjects

{

dispatch_barrier_async(self.syncQueue, ^{

CFArrayRemoveAllValues(_array);

});

}

- (NSUInteger)indexOfObject:(id)anObject{

if (!anObject)

return NSNotFound;

__block NSUInteger result;

dispatch_sync(self.syncQueue, ^{

NSUInteger count = CFArrayGetCount(_array);

result = CFArrayGetFirstIndexOfValue(_array, CFRangeMake(0, count), (__bridge const void *)(anObject));

});

return result;

return result;

}

#pragma mark - Private

- (dispatch_queue_t)syncQueue {

static dispatch_queue_t queue = nil;

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

queue = dispatch_queue_create("com.kong.NSKSafeMutableArray", DISPATCH_QUEUE_CONCURRENT);

});

return queue;

}

@end

3 調(diào)用

- (void)viewDidLoad {

[super viewDidLoad];

NSKSafeMutableArray *safeArr = [[NSKSafeMutableArray alloc] init];

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

for ( int i = 0; i < 5; i ++) {

dispatch_async(queue, ^{

NSLog(@"添加第%d個",i);

[safeArr addObject:[NSString stringWithFormat:@"%d",i]];

});

dispatch_async(queue, ^{

NSLog(@"刪除第%d個",i);

[safeArr removeObjectAtIndex:i];

});

}

// Do any additional setup after loading the view, typically from a nib.

}

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末房待,一起剝皮案震驚了整個濱河市邢羔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌桑孩,老刑警劉巖拜鹤,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異流椒,居然都是意外死亡敏簿,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門宣虾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來惯裕,“玉大人,你說我怎么就攤上這事绣硝◎呤疲” “怎么了?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵域那,是天一觀的道長咙边。 經(jīng)常有香客問我,道長次员,這世上最難降的妖魔是什么败许? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮淑蔚,結果婚禮上市殷,老公的妹妹穿的比我還像新娘。我一直安慰自己刹衫,他們只是感情好醋寝,可當我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著带迟,像睡著了一般音羞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仓犬,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天嗅绰,我揣著相機與錄音,去河邊找鬼。 笑死窘面,一個胖子當著我的面吹牛翠语,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播财边,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼肌括,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了酣难?” 一聲冷哼從身側響起谍夭,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鲸鹦,沒想到半個月后慧库,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡馋嗜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年齐板,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片葛菇。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡甘磨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出眯停,到底是詐尸還是另有隱情济舆,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布莺债,位于F島的核電站滋觉,受9級特大地震影響,放射性物質發(fā)生泄漏齐邦。R本人自食惡果不足惜椎侠,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望措拇。 院中可真熱鬧我纪,春花似錦、人聲如沸丐吓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背品追。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工份汗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留可婶,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓泼舱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親枷莉。 傳聞我的和親對象是個殘疾皇子娇昙,可洞房花燭夜當晚...
    茶點故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內(nèi)容