代码之家  ›  专栏  ›  技术社区  ›  Rob Keniger

如何从辅助线程安全地访问NSarray属性的内容?

  •  3
  • Rob Keniger  · 技术社区  · 16 年前

    我有一个应用程序(使用retain/release,而不是gc)维护 NSArray 实例变量,作为这样的属性公开:

    @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
    

    这是我为确保线程安全所需要做的全部工作,还是更复杂?

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

    1 回复  |  直到 16 年前
        1
  •  5
  •   bobDevil    16 年前

    上面的代码可以防止您同时设置数组,或者在另一个设置数组时获取数组。因为它是一个不可变的数组,所以这样可以保护数组本身。

    但是,如果“数组将改变”,您的意思是要编辑数组中的项,那么您仍然可能会遇到一些问题。例如,如果数组中填充了nsmutableStrings,并且您有一个运行的线程:

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

    还有另一个

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

    对数组的访问是安全的(一个线程必须等待另一个线程访问它),但是,对foo/bar指针(相同)的访问是不安全的,因为对“appendString”的两个调用都在@synchronized块之外。

    如果这就是您的数组将如何更改的,那么您还需要同步这些访问点。或者使用更多@synchronized块,或者其他类型的锁。见 Using Locks

    推荐文章