你可以在调用GC.Collect和GC.WaitForPendingFinalizers时遇到死锁吗?

Tes*_*ess 10 .net c# garbage-collection

鉴于以下内容:

GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();
GC.Collect(GC.MaxGeneration);
Run Code Online (Sandbox Code Playgroud)

考虑到多线程和垃圾收集模式,在什么情况下你会遇到死锁WaitForPendingFinalizers

注意:我不是在寻找你不应该打电话的原因的答案GC.Collect.

Luk*_*keH 6

// causes a deadlock when built with release config and no debugger attached
// building in debug mode and/or attaching the debugger might keep
// badIdea alive for longer, in which case you won't see the deadlock
// unless you explicitly set badIdea to null after calling Monitor.Enter

var badIdea = new BadIdea();
Monitor.Enter(badIdea);

GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();
GC.Collect(GC.MaxGeneration);

// ...

public class BadIdea
{
    ~BadIdea()
    {
        lock (this)
        {
            // ...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Cod*_*ray 5

调用时您不会遇到任何类型的死锁情况GC.CollectGC.WaitForPendingFinalizers 除非您在方法中访问托管对象Finalize。调用具有公共作用域的其他对象的方法可能会导致不可预测的结果,包括死锁。原因是您无法完全控制其他对象的锁定模式。当您的终结器方法尝试访问它时,任何人都可以锁定它。

此外,正如 LukeH 的回答所示this,在终结器中显式锁定几乎肯定会导致死锁。您可以在此处阅读 Jeffrey Richter 的原始文章。

一般来说,您应该只在终结器中释放非托管资源,这应该可以减轻有关死锁的任何此类担忧。