3

我有一个维护NSArray实例变量的应用程序(使用保留/释放,而不是 GC),该变量作为属性公开,如下所示:

@interface MyObject : NSObject
{
    NSArray* myArray;
}
@property (copy) NSArray* myArray;
@end

我想从辅助线程访问该数组的内容,该辅助线程使用-performSelectorInBackground:withObject:. 在辅助线程的执行过程中,数组可能并且确实很可能会发生变化。

在辅助线程中,我想做这样的事情:

if([self.myArray containsObject:foo])
{
    //do stuff
}

通过阅读线程文档,似乎我应该能够@synchronized在访问器中使用该指令,如下所示:

@implementation MyObject
- (NSArray *)myArray
{
    NSArray *result;
    @synchronized(self)
    {
        result = [myArray retain];
    }
    return [result autorelease];
}

- (void)setMyArray:(NSArray *)aMyArray
{
    @synchronized(self)
    {
        [myArray release];
        myArray = [aMyArray copy];
    }
}
@end

这是我需要做的所有事情来确保线程安全,还是更复杂?

更新:我随后在 Apple 网站上找到了一篇很好的文章,深入解决了这个问题:http: //developer.apple.com/mac/library/technotes/tn2002/tn2059.html

4

1 回答 1

5

您上面的代码可以防止您同时设置数组,或者在另一个设置数组时获取数组。由于它是一个非可变数组,因此可以很好地保护数组本身。

但是,如果“数组将更改”是指您将编辑数组中的项目,那么您仍然可能会遇到一些问题。例如,如果数组被 NSMutableStrings 填充,并且你有一个线程运行:

NSMutableString *foo = [myObject.myArray objectAtIndex:0];
[foo appendString:@"foo"];

另一个跑了

NSMutableString *bar = [myObject.myArray objectAtIndex:0];
[bar appendString:@"bar"];

The access to the array would be safe (one thread would have to wait for the other to access it), however, access to the foo/bar pointer (which is the same) would not be, since both calls to 'appendString' are outside of the @synchronized block.

If this is how your array will change, you'll need to synchronize these points of access as well. Either with more @synchronized blocks, or other types of locks. See Using Locks

于 2010-02-11T04:16:45.980 回答