Как разрешить одному потоку изменять свойство массива, в то время как другой поток выполняет итерацию для копии массива - PullRequest
4 голосов
/ 20 марта 2010

Я хотел бы реализовать шаблон наблюдателя в Objective-C, где наблюдатель реализует интерфейс, подобный SKPaymentTransactionObserver , а класс наблюдаемых просто расширяет мою базовую наблюдаемую. Мой наблюдаемый класс выглядит примерно так, как показано ниже. Обратите внимание, что я делаю копии наблюдателей перед подсчетом, чтобы не создавать исключение .

Я попытался добавить NSLock вокруг добавления наблюдателей и уведомить наблюдателей, но я зашел в тупик.

Как правильно обрабатывать параллелизм при добавлении наблюдателей при отправке уведомлений?

@implementation Observable

-(void)notifyObservers:(SEL)selector {
    @synchronized(self) {
        NSSet* observer_copy = [observers copy];
        for (id observer in observer_copy) {
            if([observer respondsToSelector: selector]) {
                [observer performSelector: selector];
            }
        }
        [observer_copy release];
    }
}

-(void)notifyObservers:(SEL)selector withObject:(id)arg1 withObject:(id)arg2 {
    @synchronized(self) {
 NSSet* observer_copy = [observers copy];
        for (id observer in observer_copy) {
            if([observer respondsToSelector: selector]) {
                [observer performSelector: selector withObject: arg1 withObject: arg2];
            }
        }
       [observer_copy release];
    }
}

-(void)addObserver:(id)observer {
    @synchronized(self) {
        [observers addObject: observer];
    }
}

-(void)removeObserver:(id)observer {
    @synchronized(self) {
       [observers removeObject: observer];
    }
}

Ответы [ 2 ]

2 голосов
/ 20 марта 2010

Не могли бы вы выбрать более простой способ уведомлений ?

1 голос
/ 21 марта 2010

В чем проблема с текущим кодом? Это тот, который блокирует? Не могли бы вы вспомнить конкретный сценарий тупика? Вы пытались синхронизировать только копию массива? Как это:

- (void) notify {
    @synchronized(self) {
        NSSet *observersCopy = [observers copy];
    }
    for (id observer in observersCopy)
        [observer doSomething];
    [observersCopy release];
}

- (void) addObserver: (id) observer {
    @synchronized(self) {
        [observers addObject:observer];
    }
}
...