2011-12-21 25 views
1

操作キューを使用するときに、同じ(クラス)変数を扱う方法を見つけることができませんでした。 C &では、約mutexをスレッドします。だから、NSOperationQueueが操作のためのスレッドを開始し、クラス変数が変更されたときはどうなりますか?スレッドセーフですか?ありがとうございました。スレッドセーフ:NSOperationQueue + [array addObject]

@interface MyTest { 
    NSMutableArray *_array; 
} 
@end 

-(id)init 
{ 
    ... 
    _array = [NSMutableArray new]; // class variable 

     // queue time consuming loading 
    NSOperationQueue *queue = [NSOperationQueue new]; 
    NSInvocationOperation *operation = 
     [NSInvocationOperation initWithTarget:self 
            selector:@selector(populate) 
             object:nil]; 
    [queue addOperation:operation]; 

     // start continuous processing 
    [NSTimer scheduledTimerWithTimeInterval:0.1 
            target:self 
            selector:@selector(processing) 
            userInfo:nil 
            repeats:YES]; 
    ... 
} 

-(void)populate 
{ 
    while (...) 
    { 
     id element = ...; // time consuming 

      // modify class variable "_array" from operation's thread (?) 
     [_array addObject:element]; 

      // Ok, I can do instead of addObject 
      // performSelectorOnMainThread:withObject:waitUntilDone: 
      // but is it the only way? Is it needed? 
    } 
} 

    // access and/or modify class variable "_array" 
-(void)processing 
{ 
    NSLog(@"array.count = %d", array.count); 
    for (id i in _array) 
    { 
     [_array addObject:[NSNumber numberWithInt:rand() % 100]]; 
      // etc... 
    } 
} 

答えて

1

いいえ、処理はいくつかのスレッドの中から呼び出された場合は、そのスレッドセーフではなく、いくつかの他のスレッドによって変更することができますクラス変数にいくつかの作業を行うスレッドを開始した場合、これは、スレッドセーフではありませんあなたがあなたの例でforeachループの中で配列を変更しているときに、あなたがその例外をとらえても、配列が変更されているとforeachループが見たときに例外が発生するかもしれません。プログラムは例外をスローします)...これを回避する方法の1つは、配列上の同期ブロックで行うことができます。同期されたブロックは同時に実行されません。スレッドは、1つの同期ブロックが終了するまでブロックし、例えば

-(void)populate 
    { 


     while (...) 
     { 
      id element = ...; // time consuming 

       // modify class variable "_array" from operation's thread (?) 
     @synchronized(_array) 
     { 
      [_array addObject:element]; 

     }   // Ok, I can do instead of addObject 
       // performSelectorOnMainThread:withObject:waitUntilDone: 
       // but is it the only way? Is it needed? 
     } 

    } 

     // access and/or modify class variable "_array" 
    -(void)processing 
    { 


      @synchronized(_array) 
     { 
      NSLog(@"array.count = %d", array.count); 
      for (id i in _array) 
      { 
       //you shouldnt modify the _array here you will get an exception 
        // etc... 
      } 
     } 
    } 
+0

これは明らかです。なぜこれがAppleのサイトのConcurrencyProgrammingGuide(オペレーション/キューについてのもの)に書かれていないのですか?これは '@synchronized'を初めて見る時です。スレッドについてのセクションで説明しています。 – debleek63

+0

あなたの意見では、より良い方法は何ですか: '@synchronized'を使うか' performSelectorOnMainThread'を呼び出しますか? – debleek63

+0

もう一つのこと: '_array'を' atomic'プロパティとして宣言/アクセスするオプションですか? – debleek63

関連する問題