2008-12-01 43 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