2012-07-06 52 views
0

我有代碼訪問,並在多個線程設置一個NSDictionary很多次,像這樣:使用NSDictionary線程安全崩潰?

- (BOOL)flagForItem:(NSNumber*)itemID 
{ 
    if(itemID) { 
     return [[_itemFlagDict objectForKey:itemID] boolValue] 
    } 
    return NO; 
} 

和:

- (void)setFlagForItem:(NSNumber*)itemID 
{ 
    if(itemID) { 
     NSMutableDictionary *copy = [_itemFlagDict mutableCopy]; 
     [copy setObject:[NSNumber numberWithBool:YES] forKey:itemID]; 
     _itemFlagDict = [NSDictionary dictionaryWithDictionary:copy]; 
    } 
} 

在set方法,我本來有一個的NSMutableDictionary - 這被改爲你現在看到的模式是因爲doh,NSMutableDictionary不是線程安全的。我的推理是在副本中執行突變,然後重新指定_itemFlagDict以捕獲更新。

但是,在訪問_itemFlagDict時,偶爾會發生一個EXC_BAD_ACCESS崩潰,導致我相信字典在訪問objectForKey:itemID時被重新分配。

我試過的另一種方法是在訪問器和setter方法上都使用@synchronized(_itemFlagDict)。雖然這解決了這個問題,但該代碼對性能非常敏感,並且同步訪問/分配會導致性能下降太多。

所以我的問題是,有沒有其他模式/方法可以用來避免這種不良訪問,同時不影響性能?如果優先級重要,訪問方法的執行(不一定是鐵精確度)是最重要的。

注意:我正在使用iOS 4及以上版本

+0

看看這個答案http://stackoverflow.com/questions/1986736/nsmutabledictionary-thread-safety – MrShoot 2012-07-07 04:57:22

+0

這是一個很好的例子,但我見過它之前,我認爲它的問題是,它鎖定任何選擇器正在字典上執行,我不希望自讀取將阻止以及寫入,這會降低性能 – Dfowj 2012-07-09 17:28:26

+0

你試過讀/寫鎖嗎?您可以在get方法中使用多個線程,並在set方法中使用一個寫入器。 https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/pthread.3.html – Ali 2013-03-07 20:19:33

回答