【问题标题】:.net 2.0 lock and exceptions before the try-finally. Are there any other exceptions besides thread abort?.net 2.0 锁定和 try-finally 之前的异常。除了线程中止,还有其他例外吗?
【发布时间】:2016-01-15 01:35:45
【问题描述】:

今天我遇到了这个: https://blogs.msdn.microsoft.com/ericlippert/2009/03/06/locks-and-exceptions-do-not-mix/

我使用的是 .net 2.0,所以基本上就是这段代码

lock(syncRootVar) {
    DoStuff();
}

将展开到这里

Monitor.Enter(syncRootVar);
try {
    DoStuff();
} finally {
    Monitor.Exit(syncRootVar);
}

正如 Lippert 在博客上所写,在 Enter 调用和 try-finally 块之间可能存在一个 nop 操作,这可能是引发线程中止异常并因此搞砸锁的潜在位置。

我对此有两个问题:

  • 有没有一种通用的方法来处理这种麻烦的情况并且仍然清理锁对象以免影响其他线程?
  • 是否存在其他可能导致获取锁但在 try-finally 块之前引发异常的情况?

【问题讨论】:

    标签: c# multithreading locking .net-2.0


    【解决方案1】:

    正如文章所指出的,您似乎关心的问题不再是问题。 C# 编译器已更改(并且可能使用 Roslyn 将保留更改),以便在 try/finally 内获取锁。无法获取锁但无法执行finally子句。

    现在(也正如文章指出的那样)你有一个不同的问题:如果受保护的代码块中的代码处于变异状态,异常可能会导致其他代码看到部分变异状态.这可能是也可能不是问题;通常是这样,但当然每个具体情况都是不同的。在这种情况下,某些代码可能是安全的。


    • 有没有一种通用的方法来处理这种麻烦的情况并且仍然清理锁对象以免影响其他线程?

    对于您询问的具体情况,您可以做的最大的两件事是:

    1. 不要中止线程。这总是很好的建议,应该始终遵循。如果你不中止一个线程,你就不会遇到这个问题。
    2. 使用最新版本的编译器。较新版本的编译器不会生成易受此问题影响的代码。

    • 是否存在其他可能导致获取锁但在 try-finally 块之前引发异常的情况?

    不,不是使用最新版本的编译器。连原来的情况都没有。


    现在那个讨厌的“部分突变”问题呢?好吧,您必须单独处理每种情况。但是,如果可能抛出异常,并且可能使锁处于部分突变状态,那么您将不得不添加自己的清理代码。例如:

    lock(syncRootVar) {
        try {
            DoStuff();
        } catch {
            UndoStuff();
            throw;
        }    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 2015-12-08
      • 1970-01-01
      相关资源
      最近更新 更多