2010-10-25 64 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