确实存在僵尸......在.NET? [英] Do zombies exist ... in .NET?

查看:141
本文介绍了确实存在僵尸......在.NET?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个关于.NET锁定队友的讨论。他是一个非常聪明的家伙在这两个低级和高级编程有着丰富的经验,但他与低级编程经验远远超过我的。无论如何,他认为,.NET锁定应该有望重负载下,如果可能的话,以避免僵尸线程崩溃的系统的公认的可能性很小关键系统加以避免。我经常使用锁,我不知道什么是僵尸线程是的,所以我问。我从他的解释,得到的印象是,一个僵尸线程已经终止,但不知何故仍持有到一些资源的线程。他给的僵尸线程如何打破一个系统的一个例子是一个螺纹锁固某个对象,之后开始了一些程序,然后在结尾可以释放锁之前的一些点。这种情况有系统崩溃的可能性,因为最终,试图执行该方法将导致所有等待访问将永远不会被返回的对象线程,因为这是使用锁定对象的线程已经死了。

I was having a discussion with a teammate about locking in .NET. He's a really bright guy with an extensive background in both lower-level and higher-level programming, but his experience with lower level programming far exceeds mine. Anyway, He argued that .NET locking should be avoided on critical systems expected to be under heavy-load if at all possible in order to avoid the admittedly small possibility of a "zombie thread" crashing a system. I routinely use locking and I didn't know what a "zombie thread" was, so I asked. The impression I got from his explanation is that a zombie thread is a thread that has terminated but somehow still holds onto some resources. An example he gave of how a zombie thread could break a system was a thread begins some procedure after locking on some object, and then is at some point terminated before the lock can be released. This situation has the potential to crash the system, because eventually, attempts to execute that method will result in the threads all waiting for access to an object that will never be returned, because the thread that is using the locked object is dead.

我想我得到了这个要点,但如果我是关闭基地,请让我知道。这个概念对我有意义。我不完全相信,这是在.NET中可能发生的一个真实场景。我从来没有听说过以前植物大战僵尸,但我也承认,谁也深入下级工作的程序员往往有基本面的计算(如线程)有更深的了解。我绝对看到但是锁定,价值,和我见过很多世界级的程序员杠杆锁定。我也有评估该为自己的能力有限,因为我知道,锁(OBJ)语句实际上只是语法糖:

I think I got the gist of this, but if I'm off base, please let me know. The concept made sense to me. I wasn't completely convinced that this was a real scenario that could happen in .NET. I've never previously heard of "zombies", but I do recognize that programmers who have worked in depth at lower levels tend to have a deeper understanding of computing fundamentals (like threading). I definitely do see the value in locking, however, and I have seen many world class programmers leverage locking. I also have limited ability to evaluate this for myself because I know that the lock(obj) statement is really just syntactic sugar for:

bool lockWasTaken = false;
var temp = obj;
try { Monitor.Enter(temp, ref lockWasTaken); { body } }
finally { if (lockWasTaken) Monitor.Exit(temp); }

和因为 Monitor.Enter Monitor.Exit 标记的extern 。这似乎可以想象,.NET做某种处理,保护线程接触到系统组件,可能有这样的影响,但是这是纯粹的投机,可能正是基于这样的事实,我从来没有听说过僵尸线程的之前。所以,我希望我能得到一些反馈这个位置:

and because Monitor.Enter and Monitor.Exit are marked extern. It seems conceivable that .NET does some kind of processing that protects threads from exposure to system components that could have this kind of impact, but that is purely speculative and probably just based on the fact that I've never heard of "zombie threads" before. So, I'm hoping I can get some feedback on this here:


  1. 是否有一个僵尸线程比一个更明确的定义是什么我在这里解释呢?

  2. 能否僵尸主题出现在.NET? (为什么/为什么不呢?)

  3. 如果适用,我怎么可能会迫使僵尸线程的创建在.NET?

  4. 如果适用,如何我可以利用无.NET冒着僵尸线程锁定的情况?

  1. Is there a clearer definition of a "zombie thread" than what I've explained here?
  2. Can zombie threads occur on .NET? (Why/Why not?)
  3. If applicable, How could I force the creation of a zombie thread in .NET?
  4. If applicable, How can I leverage locking without risking a zombie thread scenario in .NET?

我问这个问题有点两年多前。如今,这个事情发生了:

Update

I asked this question a little over two years ago. Today this happened:

推荐答案


  • 是否有一个僵尸线程比我在这里解释的更清楚的定义是什么?

  • Is there a clearer definition of a "zombie thread" than what I've explained here?
  • 似乎是一个不错的解释,我 - 已终止(因此不能再释放任何资源)一个线程,但其资源(如处理),却仍然和(潜在的)造成的问题

    Seems like a pretty good explanation to me - a thread that has terminated (and can therefore no longer release any resources), but whose resources (e.g. handles) are still around and (potentially) causing problems.


    • 能否僵尸主题出现在.NET? (为什么/为什么不呢?)

    • 如果适用,我怎么能强制.NET僵尸线程的创建?

    • Can zombie threads occur on .NET? (Why/Why not?)
    • If applicable, How could I force the creation of a zombie thread in .NET?

    他们肯定不,你看,我做了一个!

    They sure do, look, I made one!

    [DllImport("kernel32.dll")]
    private static extern void ExitThread(uint dwExitCode);
    
    static void Main(string[] args)
    {
        new Thread(Target).Start();
        Console.ReadLine();
    }
    
    private static void Target()
    {
        using (var file = File.Open("test.txt", FileMode.OpenOrCreate))
        {
            ExitThread(0);
        }
    }
    

    这程序启动一个线程目标打开一个文件,然后立即用的 了ExitThread 。 <击>由此产生的僵尸线程永远不会把手松开了的test.txt的文件,因此该文件将在程序终止之前(你可以用进程管理器或类似的检查)保持开放。的句柄 test.txt的不会被释放,直到 GC.Collect的被称为 - 原来它是更加困难比我想象的要创建一个僵尸线程泄漏句柄)

    This program starts a thread Target which opens a file and then immediately kills itself using ExitThread. The resulting zombie thread will never release the handle to the "test.txt" file and so the file will remain open until the program terminates (you can check with process explorer or similar). The handle to "test.txt" won't be released until GC.Collect is called - it turns out it is even more difficult than I thought to create a zombie thread that leaks handles)


    • 如果适用,我怎么能不利用.NET中冒着僵尸线程锁定的情况?

    • If applicable, How can I leverage locking without risking a zombie thread scenario in .NET?

    不要做什么,我只是做了!

    Don't do what I just did!

    只要你的代码清理后本身正确(使用安全把手或等价类,如果有非托管资源的工作),只要你不走出自己的方式杀死神秘和奇妙的方式线程(最安全的方法就是永远不要杀死线程 - 让他们自行终止正常,或通过例外情况如果需要的话),你将会有类似的东西僵尸线程的唯一方法是,如果事情已经非常错误(例如:某事在CLR错误的)。

    As long as your code cleans up after itself correctly (use Safe Handles or equivalent classes if working with unmanaged resources), and as long as you don't go out of your way to kill threads in weird and wonderful ways (safest way is just to never kill threads - let them terminate themselves normally, or through exceptions if necessary), the only way that you are going to have something resembling a zombie thread is if something has gone very wrong (e.g. something goes wrong in the CLR).

    在事实上其实际上是相当困难创造了僵尸线程(我不得不的P / Invoke成esentially告诉你在一个函数文档不叫它的C外)。例如下面的(可怕的)代码实际上不会创建一个僵尸主题。

    In fact its actually surprisingly difficult to create a zombie thread (I had to P/Invoke into a function that esentially tells you in the documentation not to call it outside of C). For example the following (awful) code actually doesn't create a zombie thread.

    static void Main(string[] args)
    {
        var thread = new Thread(Target);
        thread.Start();
        // Ugh, never call Abort...
        thread.Abort();
        Console.ReadLine();
    }
    
    private static void Target()
    {
        // Ouch, open file which isn't closed...
        var file = File.Open("test.txt", FileMode.OpenOrCreate);
        while (true)
        {
            Thread.Sleep(1);
        }
        GC.KeepAlive(file);
    }
    



    尽管做一些很可怕的错误,手柄的test.txt是还是尽快中止被称为(作为终结的一部分文件关闭这下盖使用的 SafeFileHandle 来包装它的文件句柄)

    Despite making some pretty awful mistakes, the handle to "test.txt" is still closed as soon as Abort is called (as part of the finalizer for file which under the covers uses SafeFileHandle to wrap its file handle)

    C.Evenhuis锁定例子回答可能是最简单的方法失败通过使用语句,而不是任一释放当一个线程被终止在非奇怪的方式,但是那容易地固定一个资源(在这种情况下,一个锁),或将在最后块的释放。

    The locking example in C.Evenhuis answer is probably the easiest way to fail to release a resource (a lock in this case) when a thread is terminated in a non-weird way, but thats easily fixed by either using a lock statement instead, or putting the release in a finally block.

    另请参见

    这篇关于确实存在僵尸......在.NET?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆