我正在推荐的方式在我的一个对象上创建一个符合KVC / KVO标准的可变数组:
@interface Factory {
NSMutableArray *widgets;
}
- (NSArray *)widgets;
- (void)insertObject:(id)obj inWidgetsAtIndex:(NSUInteger)idx;
- (void)removeObjectFromWidgetsAtIndex:(NSUInteger)idx;
@end
显然,这是一个棘手的线程安全问题。在insert
和remove
方法中,我锁定数组访问以防止并发修改,如recommended。
我的问题是,实施widgets
访问者的正确方法是什么?这是我的实施:
- (NSArray *)widgets {
[widgetLock lock];
NSArray *a = [[widgets copy] autorelease];
[widgetLock unlock];
return a;
}
线程安全吗?
答案 0 :(得分: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
属性的数组。
答案 1 :(得分:2)
您也可以使用语言中内置的锁定,而不是创建自己的锁:
即
- (NSArray *)widgets {
@synchronized(widgets)
{
NSArray *a = [[widgets copy] autorelease];
return a;
}
}
并在访问widgets
的所有其他方法中使用类似的锁定。 (传递给widgets
的参数@synchronized
是指实例变量,而不是方法。)
alex关于访问所包含对象的评论仍然适用。
答案 2 :(得分:0)
您需要锁定所有读写方法。如果你的插入和删除也是锁定的(就像你说的那样),那么访问器方法应该是这样的。