2010-03-20 72 views
4

我想在Objective-C中实现一个观察者模式,其中观察者实现类似于SKPaymentTransactionObserver的接口,而observable类只是扩展我的基地可观察。我可观察的类看起来像下面的内容。请注意,在枚举之前我要复制观察者,以避免投掷exception如何让一个线程改变数组属性,而另一个线程在数组副本上迭代

我试着添加一个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

当前代码有什么问题?这是一个僵局吗?你能想到具体的死锁场景吗?您是否尝试仅同步阵列副本?像这样:

- (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]; 
    } 
} 
+0

当前的代码实际上工作正常,但我不得不在迭代之前复制数组,以避免在修改数组时引发异常。我在通知周围添加了共享的NSLock,并添加了导致死锁的观察者方法。我可以发布死锁的代码。 – lolsborn 2010-03-21 06:45:16

+1

啊哈!我认为副本很好。除非证明它是一个瓶颈,否则我会忘记它。我曾经在即时游戏的主循环中复制和分配数组。 – zoul 2010-03-21 07:00:25

1

你不能选择的notifications更简单的方法?

+0

这里有一些讨论:http://www.cocoadev.com/index.pl?NotificationsAcrossThreads关于如何在多线程应用中使用NSNotification实例。一个条目使用pthreads而不是'NSLock',但原则应该大致相同。 – 2010-03-20 23:11:16

+0

通知中心似乎不适合我想要做的事情。许多通知回调采用各种参数,使用类似于SKPaymentTransactionObserver的观察者界面更加直观。 – lolsborn 2010-03-21 02:59:05

相关问题