NSLocking的使用总是应该包含在@ try/@中吗?

Tod*_*orf 11 cocoa locking exception-handling objective-c

给定一个Cocoa NSLocking对象(比如一个NSLock)和一些在执行锁定时要执行的非平凡代码:

为了确保始终释放锁定,是否应始终使用以下习惯用法?

NSLock *mutex = // get lock from somewhere
@try {
    [mutex lock];
    // do non-trivial stuff
} 
@finally {
    [mutex unlock];
}
Run Code Online (Sandbox Code Playgroud)

这似乎是谨慎的(在Java中很常见),但我没有看到任何Cocoa代码这样做.

应该使用这个成语吗?为什么或者为什么不?

jus*_*tin 4

为了确保锁始终被释放,是否应该始终使用以下习惯用法?

是的,在该范围(“非平凡的东西”)之后的程序正确性是必需的,并且假设您的程序可以正确地从遇到的异常中恢复。

应该使用这个习语吗?为什么或者为什么不?

如果可以恢复,那么是的,需要解锁才能继续正常执行。否则,您的程序将在无效状态下执行。

  • 示例 1:当锁被销毁时(在 期间dealloc),销毁它的尝试将失败,因为它仍然处于锁定状态。未定义实现是否继续破坏锁或忽略错误(我猜会持续存在,这意味着它永远不会退出dealloc)。

  • 示例 2:当它被另一个线程(或同一个线程,如果不可重入)锁定时,您将永远不会获取该锁,并且可能会产生另一个错误、死锁或异常。实现也可以(最终)在不获取锁的情况下继续进行。所保证的只是在检测到错误时/如果检测到错误时进行记录。

pthread_mutex如果你有这样的锁不平衡,es 和依赖它们的实现可能不会表现得非常优雅;这总是会归咎于程序员的错误。

纯 objc 和 c 中的正确和防御性锁定并不是很漂亮。Java 习惯用法是正确的,并且同样适用于 Foundation API。您没有看到太多的原因可能是因为异常是 Cocoa API 和依赖它们的程序中不太流行/使用的错误处理机制(与 Java 相比)。另请参阅评论中巴伐利亚的注释

  • 值得一提的是,与其他语言/库相比,Cocoa 中的异常性质相当特殊。Cocoa 异常(在大多数情况下)是在没有异常处理程序的情况下可以通过编程方式避免问题的情况下引发的(例如,在读取数组元素之前通过测试边界超出范围)或者问题很难恢复(例如,发送到的无效选择器对象,或与窗口服务器的连接已丢失)。 (3认同)