【问题标题】:Should NSLocking usage always be wrapped in @try/@finally?NSLocking 的使用是否应该始终包含在 @try/@finally 中?
【发布时间】:2011-10-12 06:08:52
【问题描述】:

给定一个 Cocoa NSLocking 对象(如 NSLock)和一些在持有锁时要执行的重要代码:

为确保始终释放锁,是否应始终使用以下成语?

NSLock *mutex = // get lock from somewhere
@try {
    [mutex lock];
    // do non-trivial stuff
} 
@finally {
    [mutex unlock];
}

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

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

【问题讨论】:

    标签: objective-c cocoa exception-handling locking


    【解决方案1】:

    为确保始终释放锁,是否应始终使用以下成语?

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

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

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

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

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

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

    纯 objc 和 c 中的正确和防御性锁定不是很漂亮。 Java 习语是正确的,同样适用于 Foundation API。您看不到它的原因可能是因为异常是 Cocoa API 和依赖它们的程序(与 Java 相比)中不太流行/使用的错误处理机制。 另见 Bavarious 在 cmets 中的注释

    【讨论】:

    • 值得一提的是,与其他语言/库相比,Cocoa 中异常的性质相当奇特。 Cocoa 异常(在大多数情况下)在没有异常处理程序的情况下可以通过编程方式防止问题(例如,在读取数组元素之前通过测试边界越界)或问题难以恢复(例如发送到的无效选择器)引发对象,或与窗口服务器的连接已丢失)。
    • @Bavarious 是的,好点子 - 我们同时打字(当你写你的评论时,我正在更新/扩展答案)。
    【解决方案2】:

    没有。

    异常仅用于 Cocoa 中的编程错误。它们不用于预计程序会恢复的情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-16
      • 2011-06-06
      • 1970-01-01
      • 1970-01-01
      • 2017-11-12
      • 1970-01-01
      • 1970-01-01
      • 2015-11-17
      相关资源
      最近更新 更多