2010-10-25 66 views
3

我有一個簡單的類,它看起來有點像這樣停止操作:啓動和以線程安全的方式

@protocol Recorder 
@property(BOOL) isRunning; 
- (void) start; 
- (void) stop; 
@end 

而且方法實現:

- (void) start { 
    if (running) 
     return; 
    … 
    running = YES; 
} 

- (void) stop { 
    if (!running) 
     return; 
    … 
    running = NO; 
} 

而且我開始思考螺紋安全。目前的解決方案不是線程安全的,對吧?這怎麼樣:

- (void) start { 
    @synchronized(self) { 
     if (running) 
      return; 
     … 
     running = YES; 
    } 
} 

這是否正確,只要-stop方法也同步?不過,我不喜歡@synchronized引入的額外嵌套。明確的鎖定工作?

- (void) stop { 
    [startStopLock lock]; 
    if (running) 
     return; 
    … 
    running = YES; 
    [startStopLock unlock]; 
} 

或者我能做這個嗎?

enum { Running, Stopped }; 
NSConditionLock *startStopLock; 

- (void) start { 
    if (![startStopLock tryLockWithCondition:Stopped]) 
     return; 
    … 
    [startStopLock unlockWithCondition:Running]; 
} 

該解決方案是否正確?你會做不同的事情嗎?

回答

1

這是什麼語言?你是對的,第一個版本不是線程安全的。

同步版本是線程安全的。有了明確的鎖定,您需要小心,不要錯過早期返回路徑上的解鎖。

如果您可以訪問鎖定的xchg內在函數,則可以通過原子交換操作輕鬆完成。 cmpxchg也可以。

start() { 
    if (locked_xchg(running, YES) == YES) { 
     // the old value was YES, so nothing to do 
     return 
    } 
+0

這是iOS上的Objective-C。謝謝'locked_xchg'提示,我有'OSAtomicTestAndSet',它應該大致相同。 – zoul 2010-10-25 15:18:32

+0

沒問題。這是人們犯的經典錯誤。不幸的是,我們的Jinx產品不能在iPhone上運行。否則,我會建議用它來幫助抓住這些比賽。 – 2010-10-25 19:05:17