首页 文章

try-finally之前的.net 2.0锁定和异常 . 除了线程中止之外还有其他例外吗?

提问于
浏览
0

今天我遇到了这个问题: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块之前出现异常?

1 回答

  • 0

    正如文章指出的那样,您似乎关注的问题不再是问题 . C#编译器已被更改(并且可能与Roslyn保留更改),以便锁定在 try / finally 内部 . 无法获取锁定但无法执行 finally 子句 .

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

    •是否有一种常见的方法来处理这种麻烦的情况并仍然清理锁定对象以免影响其他线程?

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

    • 唐't abort threads. This is always good advice and should always be followed. If you don'吨中止一个帖子,你不会有这个问题 .

    • 使用最新版本的编译器 . 较新版本的编译器不会生成容易受到问题影响的代码 .

    •是否存在可能导致获取锁定的其他情况,但是在try-finally阻止之前出现异常?

    不,不是最新版本的编译器 . 甚至没有最初的情况 .

    那那令人讨厌的"partially-mutated"问题怎么样?那么,你必须添加自己的清理代码 . 例如 . :

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

相关问题