2008-12-01 53 views
2

我對我的一個對象的推薦方式創建一個兼容KVO-KVC /可變數組:可可線程安全的可變集合訪問

@interface Factory { 
    NSMutableArray *widgets; 
} 
- (NSArray *)widgets; 
- (void)insertObject:(id)obj inWidgetsAtIndex:(NSUInteger)idx; 
- (void)removeObjectFromWidgetsAtIndex:(NSUInteger)idx; 
@end 

顯然,這是一個棘手的線程安全問題。在insertremove方法我鎖定陣列訪問以防止併發修改,如recommended

我的問題是,實現widgets訪問器的正確方法是什麼?這是我的實現:

- (NSArray *)widgets { 
    [widgetLock lock]; 
    NSArray *a = [[widgets copy] autorelease]; 
    [widgetLock unlock]; 
    return a; 
} 

它是線程安全嗎?

回答

2

您的widgets訪問器應該沒問題,但您應該知道該數組中的任何對象都沒有被鎖定。所以,你可能會遇到問題,試圖像

[[[myFactory widgets] objectAtIndex:7] setName:@"mildred"]; 

[myTextField setStringValue:[[[myFactory widgets] objectAtIndex:7] name]]; // mildred? or something else? 

同時運行的代碼,因爲你的數組中的對象不會被鎖定,你可能會遇到競爭條件或讀/寫器型問題。多線程不是一種快樂嗎?

另一方面,爲了符合KVC,我建議實施objectInWidgetsAtIndex:countOfWidgets而不是widgets存取器。請記住,KVC建模關係,而不是數組屬性。所以你會打電話[myFactory mutableArrayValueForKey:@"widgets"]來獲得代表widgets屬性的數組。

0

您將需要鎖定所有讀取和寫入方法。如果你的插入和移除也是鎖定的(就像你說的那樣),那麼accessor方法應該是這樣的。

2

比創建自己的鎖定相反,您還可以使用內置的語言鎖定:

- (NSArray *)widgets { 
    @synchronized(widgets) 
    { 
     NSArray *a = [[widgets copy] autorelease]; 
     return a; 
    } 
} 

和訪問widgets其他所有方法都使用類似的鎖定。 (參數widgets傳入@synchronized是指實例變量,而不是方法。)

alex有關訪問包含對象的註釋仍然適用。

+0

@synchronized實際上已被棄用,但比NSLock慢。 – Frizlab 2013-11-01 21:55:54