ゾンビは.NETに存在しますか?


385

.NETでのロックについてチームメイトと話し合っていました。彼は非常に優秀で、低レベルのプログラミングと高レベルのプログラミングの両方に豊富なバックグラウンドを持っていますが、低レベルのプログラミングでの彼の経験は私のものをはるかに超えています。とにかく、彼は、「ゾンビスレッド」がシステムをクラッシュさせる確かに小さな可能性を回避するために、可能な限り高負荷になることが予想される重要なシステムでは.NETロックを回避すべきであると主張しました。私は日常的にロックを使用していて、「ゾンビスレッド」が何であるかを知らなかったので、私は尋ねました。彼の説明から私が得た印象は、ゾンビスレッドは終了したが、どういうわけかいくつかのリソースをまだ保持しているスレッドであるということです。ゾンビスレッドがシステムを破壊する方法について彼が示した例は、スレッドが何らかのオブジェクトをロックした後に何らかの手順を開始した場合でした。そして、ロックが解放される前に、ある時点で終了します。この状況は、システムをクラッシュさせる可能性があります。最終的には、そのメソッドを実行しようとすると、ロックされたオブジェクトを使用しているスレッドが停止しているため、スレッドがすべて返されないオブジェクトへのアクセスを待機するためです。

要点は理解できたと思いますが、ベースがずれている場合はお知らせください。そのコンセプトは私には理にかなっています。これが.NETで発生する可能性のある実際のシナリオであることを完全には確信していませんでした。これまで「ゾンビ」について聞いたことがありませんが、低レベルで深く作業したプログラマーは、コンピューティングの基礎(スレッド化など)をより深く理解する傾向があることを認識しています。しかし、私は確実にロックの価値を見ていますし、多くの世界クラスのプログラマーがロックを活用しているのを見てきました。また、私はこれを自分で評価する能力が限られています。これは、このlock(obj)ステートメントが本当に次の構文糖衣であることを知っているためです。

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

そしてのでMonitor.EnterMonitor.Exitマークされていますextern。.NETがこの種の影響を与える可能性のあるシステムコンポーネントへの暴露からスレッドを保護する何らかの処理を行うことは考えられるようですが、これは純粋に推測であり、おそらく「ゾンビスレッド」について聞いたことがないという事実に基づいているだけです。前。だから、私はこれについてここでいくつかのフィードバックを得ることができることを望んでいます:

  1. ここで説明したものよりも「ゾンビスレッド」の明確な定義はありますか?
  2. ゾンビスレッドは.NETで発生しますか?(なぜ/なぜそうではないのですか?)
  3. 該当する場合、.NETでゾンビスレッドの作成を強制するにはどうすればよいですか?
  4. 該当する場合、.NETでゾンビスレッドのシナリオを危険にさらすことなくロックを活用するにはどうすればよいですか?

更新

私は2年以上前にこの質問をしました。今日これが起こりました:

オブジェクトはゾンビ状態です。


8
あなたの同僚がデッドロックについて話していませんか?
Andreas Niedermair 2013年

10
@AndreasNiedermair-デッドロックとは何か知っていますが、明らかにその用語の誤用の問題ではありませんでした。デッドロックは会話で言及され、「ゾンビスレッド」とは明らかに異なっていました。私にとっての主な違いは、ゾンビスレッドは一方向であり、終了したプロセスが必要なのに対して、デッドロックには解決できない双方向の依存関係があることです。あなたが同意せず、これらのものを見るより良い方法があると思うなら、説明してください
smartcaveman '19

19
「ゾンビ」という言葉は、実際には「ゾンビプロセス」のように、UNIXのバックグラウンドに由来すると思いますよね??? UNIXには「ゾンビプロセス」の明確な定義があります。これは、終了した子プロセスを記述しますが、子プロセスの親は、waitまたはを呼び出して、子プロセス(およびそのリソース)を「解放」する必要がありますwaitpid。子プロセスは「ゾンビプロセス」と呼ばれます。howtogeek.com/119815
hogliux

9
プログラムの一部がクラッシュし、プログラムが未定義の状態のままになっている場合は、もちろん、プログラムの残りの部分で問題が発生する可能性があります。シングルスレッドプログラムで例外を不適切に処理した場合も、同じことが起こります。問題はスレッドにあるのではなく、問題はグローバルな変更可能な状態にあり、予期しないスレッドの終了を適切に処理していないことです。あなたの「本当に明るい」同僚は、これに完全に基づいていません。
ジムミッシェル2013年

9
「最初のコンピューター以来、マシンには常にゴーストが存在していました。予期しないプロトコルを形成するためにグループ化されたコードのランダムセグメント...」
Chris Laplante 2013年

回答:


242
  • ここで説明したものよりも「ゾンビスレッド」の明確な定義はありますか?

私にはかなり良い説明のようです-終了した(したがってリソースを解放できなくなった)スレッドですが、そのリソース(ハンドルなど)はまだ残っており、(潜在的に)問題を引き起こしています。

  • ゾンビスレッドは.NETで発生しますか?(なぜ/なぜそうではないのですか?)
  • 該当する場合、.NETでゾンビスレッドの作成を強制するにはどうすればよいですか?

彼らは確かに、見て、私はそれを作った!

[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);
    }
}

このプログラムは、Targetファイルを開くスレッドを開始し、を使用してすぐに自分自身を強制終了しExitThreadます。 結果のゾンビスレッドは「test.txt」ファイルへのハンドルを解放しないため、プログラムが終了するまでファイルは開いたままになります(プロセスエクスプローラーなどで確認できます)。 「test.txt」へのハンドルGC.Collectは、呼び出されるまで解放されません-ハンドルをリークするゾンビスレッドを作成することを考えるよりもさらに難しいことがわかります)

  • 該当する場合、.NETでゾンビスレッドのシナリオを危険にさらすことなくロックを活用するにはどうすればよいですか?

私がやったことをしないでください!

コードが正しくクリーンアップされる限り(アンマネージリソースを操作する場合は、セーフハンドルまたは同等のクラスを使用します)、奇妙で素晴らしい方法でスレッドを強制終了する方法を使用しない限り(最も安全な方法は、スレッドを強制終了しないようにするには-スレッドを正常に終了させるか、必要に応じて例外を介して)、ゾンビスレッドに似たものを作成する唯一の方法は、何かが非常にうまくいかない場合(CLRで何かがうまくいかないなど)です。

実際、ゾンビスレッドを作成することは実際には驚くほど困難です(ドキュメントでCの外部で呼び出さないように本質的に指示する関数にP / Invokeする必要がありました)。たとえば、次の(ひどい)コードは実際にはゾンビスレッドを作成しません。

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"へのハンドルAbortは呼び出されるとすぐに閉じられます(ファイナライザーの一部として、内部でSafeFileHandlefile使用してファイルハンドルをラップするため)

C.Evenhuis回答のロックの例は、スレッドが非奇妙な方法で終了したときにリソース(この場合はロック)を解放できない最も簡単な方法ですが、lock代わりにステートメントを使用するか、またはリリースをfinallyブロックに入れます。

こちらもご覧ください


3
バックグラウンドワーカーを使用してExcelでデータを保存して遊んだとき、すべてのリソースを常に解放しなかったのを覚えています(デバッグをスキップしただけなので)。その後、タスクマネージャーで約50のExcelプロセスを確認しました。zombieexcelprocessesを作成しましたか?
Stefan

3
@ジャスティン-+1-すばらしい答えです。私はあなたのExitThread電話に少し懐疑的です。明らかに、それは機能しますが、現実的なシナリオよりも巧妙なトリックのように感じられます。私の目標の1つは、.NETコードで誤ってゾンビスレッドを作成しないように、すべきでないことを学ぶことです。おそらく、.NETコードから問題を引き起こすことが知られているC ++コードを呼び出すと、望ましい効果が得られることを理解できただろう。あなたは明らかにこのことについてたくさん知っています。同じ結果が得られる他のケース(奇妙な可能性がありますが、意図せずに発生しないほど変ではない)を知っていますか?
smartcaveman 2013年

3
したがって、答えは「C#4にはない」ですよね?ゾンビスレッドを取得するためにCLRからジャンプする必要がある場合、それは.Netの問題のようには見えません。
Gusdor 2013年

4
@Stefan私はほぼ間違いなくそう言うでしょう。私はあなたが説明したことを何度もしました。Excelプロセスはゾンビではありません。通常のUIからすぐにはアクセスできませんが、実行中です。GetObjectの呼び出しを介してそれらを取得できるはずですSet excelInstance = GetObject(, "Excel.Application")
ダニエル

7
「結果のゾンビスレッドは「test.txt」ファイルへのハンドルを解放しないため、プログラムが終了するまでファイルは開いたままになります」は正しくありません。小さな証明: `static void Main(string [] args){new Thread(GcCollect).Start(); 新しいThread(Target).Start(); Console.ReadLine(); } private static void Target(){using(var file = File.Open( "test.txt"、FileMode.OpenOrCreate)){ExitThread(0); }} private static void GcCollect(){while(true){Thread.Sleep(10000); GC.Collect(); }} `
Sinix 2013年

46

私は私の答えを少し整理しましたが、参考のために元の答えを下に残しました

ゾンビという言葉を聞いたのはこれが初めてなので、その定義は次のように想定します。

すべてのリソースを解放せずに終了したスレッド

したがって、その定義があれば、そうです。他の言語(C / C ++、java)と同様に、.NETでもそれを行うことができます。

ただし、これは.NETでスレッド化されたミッションクリティカルなコードを記述しない理由としては適切ではないと思います。.NETに対して決定する他の理由があるかもしれませんが、ゾンビスレッドを持つことができるという理由だけで.NETをオフに書くことは、私には意味がありません。ゾンビスレッドはC / C ++で可能です(Cを台無しにするほうがはるかに簡単だと私はさえ主張します)、そして多くの重要なスレッド化されたアプリはC / C ++(大量取引、データベースなど)にあります。

結論 使用する言語を決定している場合は、全体像を考慮に入れることをお勧めします。パフォーマンス、チームスキル、スケジュール、既存のアプリとの統合などです。確かに、ゾンビスレッドは考慮すべきものです。 、しかしCのような他の言語と比較して実際に.NETでこの間違いを犯すことは非常に難しいので、この懸念は上記のような他のものによって覆い隠されると思います。幸運を!

元の回答 ゾンビは、適切なスレッドコードを記述しないと存在する可能性があります。C / C ++やJavaなどの他の言語についても同様です。しかし、これが.NETでスレッドコードを記述しない理由ではありません。

そして、他の言語と同じように、何かを使用する前に価格を知ってください。また、潜在的な問題を予測できるように、内部で何が起こっているかを知るのにも役立ちます。

ミッションクリティカルなシステムの信頼性の高いコードは、どんな言語を使用していても簡単に書くことはできません。しかし、.NETで正しく実行することは不可能ではないのは確かです。また、.NETスレッディングはC / C ++のスレッディングとそれほど違いはなく、一部の.net固有の構成(RWLやイベントクラスの軽量バージョンなど)を除いて、同じシステムコールを使用(またはビルド)します。

ゾンビという用語を初めて聞いたが、あなたの説明に基づいて、あなたの同僚はおそらく、すべてのリソースを解放せずに終了したスレッドを意味していた。これにより、デッドロック、メモリリーク、またはその他の悪影響が発生する可能性があります。これは明らかに望ましいことではありませんが、他の言語でも可能であるため、この可能性のために.NETを1つに分離することはおそらくお勧めできません。.NETよりもC / C ++で台無しにした方が簡単だとさえ主張しますが(特に、RAIIがないCでは)、重要なアプリの多くはC / C ++で書かれていますか?ですから、それは本当にあなたの個々の状況に依存します。アプリケーションからあらゆる速度を引き出し、可能な限りベアメタルに近づけたい場合、.NET 最善の解決策ではありません。予算が限られていて、Webサービス/既存の.netライブラリなどとの多くのインターフェイスを使用している場合は、.NETが限られていて場合は選択することを


(1)行き止まりのexternメソッドを実行したときに、内部で何が起こっているのかを理解する方法がわかりません。ご提案がございましたら、ぜひお聞かせください。(2).NETで実行できることに同意します。ロックでそれが可能であると信じたいのですが、今日それを正当化するための満足のいく答えをまだ見つけていません
smartcaveman

1
@smartcaveman意味するところlockinglockキーワードの場合、実行をシリアル化するため、おそらくそうではありません。スループットを最大化するには、コードの特性に応じて適切な構成を使用する必要があります。pthreads / boost / thread pools / whateverを使用してc / c ++ / java / whateverで信頼性の高いコードを記述できれば、C#でも記述できます。しかし、ライブラリを使用して信頼性のあるコードを任意の言語で記述できない場合、C#での記述はそれとは異なると思います。
Jerahmeel、2013年

@smartcavemanボンネットの下にあるものを把握することに関しては、Googleがヒープを支援します。問題がエキゾチックすぎてWeb上で見つけることができない場合、リフレクターは非常に便利です。しかし、スレッドクラスについては、MSDNのドキュメントが非常に役立ちます。そして、その多くは、Cで使用するのと同じシステムコールのラッパーにすぎません。
Jerahmeel、2013年

1
@smartcavemanまったくそうではありません。そんなふうに出会ってすみません。私が言いたかったのは、重要なアプリケーションを作成するときに、.NETを書くのが速すぎてはいけないということです。確かに、ゾンビスレッド(他の言語で完全に発生する可能性のあるアンマネージリソースを解放しなかっただけのスレッドだと思います)よりもはるかに悪いことができますが、stackoverflow.com / questions / 14268080 / ですが、繰り返しますが、.NETが実行可能なソリューションではないという意味ではありません。
Jerahmeel、2013年

2
.NETは悪いテクノロジーだとはまったく思いません。それは実際には私の主要な開発フレームワークです。しかし、そのため、私はそれが影響を受けやすい欠陥を理解することが重要だと思います。基本的に、私は.NETを選択していますが、好きだからではなく、好きでないからではありません。(心配しないでください、私はあなたを+1しました)
smartcaveman 2013年

26

現在、私の答えのほとんどは、以下のコメントによって修正されています。コメントの情報は読者にとって価値があるかもしれないので、評判ポイントが必要なので、私は回答を削除しません。

イモータル・ブルーは、.NET 2.0以降のfinallyブロックではスレッドのアボートの影響を受けないことを指摘しました。そして、Andreas Niedermairのコメントによると、これは実際のゾンビスレッドではない可能性がありますが、次の例は、スレッドを中止すると問題が発生する方法を示しています。

class Program
{
    static readonly object _lock = new object();

    static void Main(string[] args)
    {
        Thread thread = new Thread(new ThreadStart(Zombie));
        thread.Start();
        Thread.Sleep(500);
        thread.Abort();

        Monitor.Enter(_lock);
        Console.WriteLine("Main entered");
        Console.ReadKey();
    }

    static void Zombie()
    {
        Monitor.Enter(_lock);
        Console.WriteLine("Zombie entered");
        Thread.Sleep(1000);
        Monitor.Exit(_lock);
        Console.WriteLine("Zombie exited");
    }
}

ただし、lock() { }ブロックを使用しているfinally場合は、ThreadAbortExceptionそのように起動されたときにもが実行されます。

次の情報は、結局のところ、.NET 1および.NET 1.1に対してのみ有効です。

lock() { }ブロック内で他の例外が発生し、ブロックが実行されようとしているThreadAbortExceptionときにが到着した場合finally、ロックは解放されません。あなたが述べたように、lock() { }ブロックは次のようにコンパイルされます:

finally 
{
    if (lockWasTaken) 
        Monitor.Exit(temp); 
}

Thread.Abort()生成されたfinallyブロック内で別のスレッドが呼び出すと、ロックが解除されない場合があります。


2
あなたが話しているlock()が、私はこれの使用法を見ることができません...だから-これはどのように接続されていますか?これは、の「間違った」用法であるMonitor.EnterMonitor.Exit(の使用を欠いているtryfinally
アンドレアスNiedermair

4
これは単に間違った用法である-私はゾンビスレッドことを呼び出すことはありませんMonitor.EnterMonitor.Exitの適切な使用なしtryfinally-あなたのシナリオはにハングアップする可能性のある他のスレッドをロックします、とにかく_lock必ずしもゾンビスレッド- 、そのデッドロック・シナリオがあります...また、あなたはロックを解除していませんMain...しかし、ねえ...おそらくOPはゾンビスレッドではなくデッドロックのためにロックしています:)
Andreas Niedermair

1
@AndreasNiedermairおそらく、ゾンビスレッドの定義は、私が思っていたものとはまったく異なります。おそらく、これを「実行を終了したがすべてのリソースを解放していないスレッド」と呼ぶことができます。宿題を削除してやりたくなったが、OPのシナリオとの類似性を保つために答えを残した。
C.Evenhuis 2013年

2
ここに罪はない!実際、あなたの答えは私にそれについて考えさせてくれました:) OPはロックが解放されていないことを明示的に話しているので、私は彼の仲間がデッドロックについて話していると思います-ロックはスレッドにバインドされている実際のリソースではないためです(それは共有されます...nöna)-したがって、「ゾンビ」スレッドは、ベストプラクティスに固執しlock、適切に使用することによって回避できますtry/finally
Andreas Niedermair

1
@ C.Evenhuis-私の定義が正確かどうかはわかりません。私が質問している理由の1つは、これを解決することです。このコンセプトはC / C ++でよく言及されていると思います
smartcaveman '19

24

これはゾンビスレッドに関するものではありませんが、Effective C#の本にはIDisposableの実装に関する項目(項目17)があり、興味深いと思うかもしれないゾンビオブジェクトについて説明しています。

本自体を読むことをお勧めしますが、その要点は、IDisposableを実装するか、またはDesctructorを含むクラスがある場合、リソースを解放することだけです。ここで他のことを行うと、オブジェクトがガベージコレクションされない可能性がありますが、まったくアクセスできなくなります。

以下のような例を示します。

internal class Zombie
{
    private static readonly List<Zombie> _undead = new List<Zombie>();

    ~Zombie()
    {
        _undead.Add(this);
    }
}

このオブジェクトのデストラクタが呼び出されると、それ自体への参照がグローバルリストに配置されます。つまり、プログラムの存続期間中、メモリ内に存在し続けますが、アクセスできません。これは、リソース(特にアンマネージリソース)が完全に解放されず、あらゆる種類の潜在的な問題を引き起こす可能性があることを意味します。

より完全な例を以下に示します。foreachループに到達するまでに、Undeadリストには150個のオブジェクトがあり、それぞれにイメージが含まれていますが、イメージはGCされており、使用しようとすると例外が発生します。この例では、画像を保存しようとしたり、高さや幅などの寸法を表示したりする場合でも、画像を操作しようとするとArgumentException(パラメーターが無効)になります。

class Program
{
    static void Main(string[] args)
    {
        for (var i = 0; i < 150; i++)
        {
            CreateImage();
        }

        GC.Collect();

        //Something to do while the GC runs
        FindPrimeNumber(1000000);

        foreach (var zombie in Zombie.Undead)
        {
            //object is still accessable, image isn't
            zombie.Image.Save(@"C:\temp\x.png");
        }

        Console.ReadLine();
    }

    //Borrowed from here
    //http://stackoverflow.com/a/13001749/969613
    public static long FindPrimeNumber(int n)
    {
        int count = 0;
        long a = 2;
        while (count < n)
        {
            long b = 2;
            int prime = 1;// to check if found a prime
            while (b * b <= a)
            {
                if (a % b == 0)
                {
                    prime = 0;
                    break;
                }
                b++;
            }
            if (prime > 0)
                count++;
            a++;
        }
        return (--a);
    }

    private static void CreateImage()
    {
        var zombie = new Zombie(new Bitmap(@"C:\temp\a.png"));
        zombie.Image.Save(@"C:\temp\b.png");
    }
}

internal class Zombie
{
    public static readonly List<Zombie> Undead = new List<Zombie>();

    public Zombie(Image image)
    {
        Image = image;
    }

    public Image Image { get; private set; }

    ~Zombie()
    {
        Undead.Add(this);
    }
}

繰り返しになりますが、特にゾンビスレッドについて質問していたことは承知しておりますが、質問のタイトルは.netのゾンビに関するものです。


1
これは面白い。され_undead、静的であることが意味?
smartcaveman

1
そこで、「破壊された」オブジェクトを印刷して試してみました。それを通常のオブジェクトのように扱います。これを行うことについて何か問題がありますか?
smartcaveman

1
うまくいけば問題をもう少し明確に示す例で私の答えを更新しました。
JMK 2013年

1
なぜあなたが反対票を投じたのか分かりません。参考になりました。ここに質問があります-どのような例外が発生しますか?NullReferenceException不足しているものをアプリケーションよりもマシンに結び付ける必要があると感じるので、それがになるとは思いません。これは正しいですか?
smartcaveman 2013年

4
確かにそれIDisposableは問題ではありません。ファイナライザ(デストラクタ)について懸念を抱きましたがIDisposable、オブジェクトをファイナライザキューに入れず、このゾンビシナリオのリスクを冒すだけではありませんでした。この警告はファイナライザに関するものであり、Disposeメソッドを呼び出す可能性があります。IDisposableファイナライザのない型で使用される例があります。感情はリソースのクリーンアップに関するものでなければなりませんが、それは重要なリソースのクリーンアップである可能性があります。RX IDisposableはサブスクリプションのクリーンアップに有効に使用し、他のダウンストリームリソースを呼び出すことができます。(私はどちらにも反対票を投じなかった...)
ジェームズワールド

21

高負荷の重要なシステムでは、主にパフォーマンスが向上するため、ロックフリーコードの記述の方が優れています。LMAXのようなものを見て、LMAXが「機械的な同情」をどのように活用しているかについて、このことについてのすばらしい議論をご覧ください。ゾンビのスレッドが心配ですか?これは、解決すべきバグにすぎず、を使用しない十分な理由ではないエッジケースだと思いますlock

あなたの友人が私に空想のエキゾチックな用語の彼の知識を誇示しているだけのように聞こえます!Microsoft UKでパフォーマンスラボを運営している間、.NETでこの問題が発生することはありませんでした。


2
経験の異なるセットは私たちが異なるバグについて偏執的になると思います。彼はそれを説明する際に極端なエッジケースであることを認めましたが、それが本当にエッジケースであり決してネバーケースではない場合、私は少なくとも少しはそれをもっとよく理解したいと思います
smartcaveman

1
けっこうだ。私はあなたがそのlock発言について過度に心配することを望まないでしょう!
James World

1
この問題をより深く理解できれば、それほど心配する必要はありません。
smartcaveman 2013年

4
あまりにも多くのスレッドFUDを取り除こうとしているため、賛成しました。Lock-FUDは処分するのにより多くの作業が必要です:)開発者が(パフォーマンスのために)無制限のスピンロックを取得すると、50Kのデータをワイドキューにコピーできるようになります。
マーティンジェームズ

3
はい、一般的および特定の両方で。ロックフリーの正しいコードを書くことは、プログラミングと同じくらい難しいものです。大多数のケースでの私の経験では、(比較的)簡単に理解できる大きな脂肪のコースlockは問題ありません。必要になるまで、パフォーマンスの最適化のために複雑さを導入することは避けます。
James World

3

1.「ゾンビスレッド」の定義は、ここで説明したものよりも明確ですか?

私は「ゾンビスレッド」が存在することに同意します。これは、手放せずに完全に死なないリソースが残っているスレッドで何が起こるかを指す用語であるため、「ゾンビ」という名前なので、この紹介の説明はお金でかなり正しいです!

2.ゾンビスレッドは.NETで発生しますか?(なぜ/なぜそうではないのですか?)

はい、発生する可能性があります。これは参照であり、実際にはWindowsでは「ゾンビ」と呼ばれています。MSDNは、デッドプロセス/スレッドに「ゾンビ」という単語を使用しています。

頻繁に起こることは別の話であり、スレッドロックのようなあなたのコーディングテクニックと実践に依存し、しばらくの間それを行ってきましたが、私はそのシナリオがあなたに起こることさえ心配していません。

そして、はい、@ KevinPankoがコメントで正しく述べられているように、「ゾンビスレッド」はUnixから来ているため、XCode-ObjectiveCで使用され、「NSZombie」と呼ばれ、デバッグに使用されます。それはほとんど同じように動作します...唯一の違いは、コード内の潜在的な問題である可能性がある「ゾンビスレッド」ではなく、デバッグ用の「ゾンビオブジェクト」になることです。


1
しかし、MSDNがゾンビを使用する方法は、この質問がゾンビを使用する方法とは大きく異なります。
Ben Voigt

1
はい、同意しますが、MSDNでさえ、スレッドが死んだとき、スレッドをゾンビスレッドと呼ぶことにしました。そして実際にそれらが発生する可能性があること。
SH

4
確かに、それはスレッドが終了したときにリソースへのハンドルを保持しているスレッドではなく、スレッドへのハンドルを保持している他のいくつかのコードを参照しています。問題の定義に同意する最初の文が間違っています。
Ben Voigt

1
ああ、私はあなたの要点を理解しています。正直、気づかなかった。私は彼がその定義がどのように起こるかに関係なく存在するという点に焦点を合わせていました。定義が存在するのは、スレッドに何が起こるかではなく、どのように行われるかということです。
SH

0

ゾンビのスレッドを簡単に作ることができます。

var zombies = new List<Thread>();
while(true)
{
    var th = new Thread(()=>{});
    th.Start();
    zombies.Add(th);
}

これにより、スレッドハンドルがリークします( Join())。管理された世界に関する限り、これはもう1つのメモリリークです。

さて、実際にロックを保持する方法でスレッドを強制終了することは、後の苦痛ですが、可能です。他の男ExitThread()は仕事をします。彼が見つけたように、ファイルハンドルはGCによってクリーンアップされましたがlock、オブジェクトの周りはクリーンアップされませんでした。しかし、なぜそうするのでしょうか。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.