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"];

配列へのアクセスは安全です(一方のスレッドはもう一方のスレッドがそれにアクセスするのを待つ必要があります)が、foo / barポインター(同じ)へのアクセスは安全ではありません。これは、'appendString'への両方の呼び出しが@synchronizedブロックの外側。

これがアレイの変更方法である場合は、これらのアクセスポイントも同期する必要があります。より多くの@synchronizedブロック、または他のタイプのロックのいずれかを使用します。ロックの使用を参照してください

于 2010-02-11T04:16:45.980 に答える