0

4つの異なるスレッドすべてが作業を終了したときに通知を発行したいと思います。私はスレッドの総数を数え続けており、スレッドが終了したときにいくつかの作業を行うリスナーがあります。

これを行うための安全な方法は次のとおりですか?

// ivars:
NSMutableArray *list;
OSSpinLock lock;

#define MAX_ALLOWED 4

- (void)someThreadedWork
{
    // Iterate thru 4 different items using gcd and update
    for (int x = 0; x < MAX_ALLOWED; ++x)
    {
        dispatch_async(some_queue, ^{
           // Do some work.. once done, 
           [self updateCount:ix];
        });
    }
}

- (void)updateCount:(NSInteger)newCount
    OSSpinLockLock(&lock);
    {
        [list addObject:[NSNumber numberWithInt:newCount]];

        if ([list count] == MAX_ALLOWED)
        {
            _allValuesUpdatedAt = [NSDate date];
        }
    }
    OSSpinLockUnlock(&lock);
}

- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object 
change:(NSDictionary*)change context:(void*)context 
{
    // When I get the 'allItemsUpdatedAt' event, I will perform some other work
}

- (id)init {
    if (self = [super init])
    {
        // there is a corresponding removeObserver in the dealloc
        list = [[NSMutableArray alloc] init];
        [anInstance addObserver:self 
                forKeyPath:@"allItemsUpdatedAt" 
                options:NSKeyValueObservingOptionNew 
                context:NULL];
    }
    return self;
}
4

2 に答える 2

1

dispatch_asyncに関するHachiEthanのコメントは正確に正しいです。代わりにdispatch_group_asyncを使用する場合は、ロックはまったく必要ありません。また、現在機能しているスレッドを追跡する必要もありません。それはあなたのためにこれのすべてをします。

この問題へのより速く、より単純で、より堅牢で、エネルギー集約的でないアプローチについては、並行性プログラミングガイドの「キューに入れられたタスクのグループを待つ」を参照してください。スレッドベースのシステムをキューベースのシステムに変換する方法については、同じドキュメントの「スレッドからの移行」も参照してください。

于 2012-08-29T20:05:21.847 に答える
0

ここにいくつかのことがあります:

危険信号:ロック内の値を変更しました_allValuesUpdatedAtが、他の場所でその値を「読み取っている」可能性があります...(たとえば、プロパティを監視している人)プロパティが同じインスタンスによって保護されていallValuesUpdatedAtない限り、問題が発生しますそこの。(編集:また、上記のコードはNSDateを保持していないため、ある時点で自動リリースされます。)allValuesUpdatedAt&lock

シリアルキューを使用dispatch_asyncして渡す場合、メソッドがそのシリアルキューから実行されているコードによってのみアクセスされる場合は、の値を更新するためにそのスピンロックは必要ありません。(:へのアクセスを保護する必要があります)listupdateCount:allValuesUpdatedAt

他のコード、たとえばメインスレッドからアクセスする必要がある場合updateCount:は、はい、あなたが持っているように、そこにある種のロックが必要になります。


編集:あなたが持っているもののほとんどを保持しますが、赤旗に対処します

//header:
@property (atomic, retain) NSDate *allValuesUpdatedAt;

//impl:
- (void)updateCount:(NSInteger)newCount
    OSSpinLockLock(&lock);
    {
        [list addObject:[NSNumber numberWithInt:newCount]];

        if ([list count] == MAX_ALLOWED)
        {
            //use atomic property for read/write thread-safety:
            self.allValuesUpdatedAt = [NSDate date]; 
        }
    }
    OSSpinLockUnlock(&lock);
}
于 2012-08-29T19:00:45.660 に答える