[解決済み】.NETにゾンビは存在するのか......?
質問
チームメイトと.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.Enter
そして
Monitor.Exit
はマークされています。
extern
. .NETは、このような影響を及ぼす可能性のあるシステム コンポーネントへの露出からスレッドを保護する何らかの処理を行うことが考えられるようですが、これは純粋に推測であり、おそらく私がこれまで「ゾンビ スレッド」という言葉を聞いたことがないという事実に基づいているだけでしょう。 ですから、この件に関するフィードバックをここで得られることを期待しています。
- ゾンビスレッドの明確な定義がありますか?
- .NETでゾンビスレッドは発生しますか? (なぜ/なぜそうしないのか?)
- 該当する場合、.NETでゾンビスレッドを強制的に作成するにはどうすればよいですか?
- 該当する場合、.NETでゾンビスレッドシナリオのリスクを負わずにロックを活用するにはどうすればよいですか?
更新情報
この質問をしたのは、2年ちょっと前です。 今日、こんなことがありました。
解決方法は?
- ここで説明したものより、もっと明確なゾンビ・スレッドの定義がありますか?
終了した(したがって、もはやリソースを解放できない)スレッドですが、そのリソース(例えばハンドル)がまだ残っていて、(潜在的に)問題を引き起こしているのです。
- .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
のファイナライザーの一部として)呼び出されます。
file
を使用していますが、これは
SafeFileHandle
を使用してファイルハンドルをラップしています)。
のロックの例は
C.Evenhuisの回答
は、スレッドが変な方法で終了したときにリソース(この場合はロック)の解放に失敗する最も簡単な方法でしょうが、その場合は
lock
ステートメントで代用するか、リリースを
finally
ブロックを作成します。
以下もご参照ください。
-
C#のILの微妙な違い
コードジェン
に対して
非常に
例外が発生するとロックが解除されないという微妙なケース。
を使用しても解放されます。
lock
キーワードを使用します (ただし、.Net 3.5 以前のバージョンでのみ使用可能)。 - ロックと例外は 混ぜる
関連
-
[解決済み】ソケットのアドレス(プロトコル/ネットワークアドレス/ポート)は、通常1つしか使用できない?
-
[解決済み】EF 5 Enable-Migrations : アセンブリにコンテキストタイプが見つかりませんでした
-
[解決済み] .NETでのdecimal, float, doubleの違い?
-
[解決済み] .NETでC#オブジェクトをJSON文字列に変換するには?
-
[解決済み] .NETでフォーマット文字列のブレース(中括弧)をエスケープする方法
-
[解決済み] .NETコンソールアプリケーションでアプリケーションのパスを取得するにはどうすればよいですか?
-
[解決済み] .NET String.Format()で数値の千の位にカンマを追加する
-
[解決済み] .NETでGmailを使ったメール送信
-
[解決済み] .NETでapp.configやweb.configから設定を読み込む
-
[解決済み] Javaでsynchronized(this)を避けるには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】プログラム実行中に1秒待つ
-
[解決済み】スクリプトクラスが見つからないので、スクリプトコンポーネントを追加できない?
-
[解決済み] メンバー '<メンバー名>' にインスタンス参照でアクセスできない
-
[解決済み】ソケットのアドレス(プロトコル/ネットワークアドレス/ポート)は、通常1つしか使用できない?
-
[解決済み】「入力文字列が正しい形式ではありませんでした」エラーの解決方法は?[重複しています]。
-
[解決済み】Swashbuckle/Swagger + ASP.Net Core: "Failed to load API definition" (API定義の読み込みに失敗しました
-
[解決済み】Visual Studio: 操作を完了できませんでした。パラメータが正しくありません
-
[解決済み】インデックスが範囲外でした。コレクションパラメータname:indexのサイズより小さく、非負でなければなりません。
-
[解決済み】画像のペイントにTextureBrushを使用する方法
-
VSでscanfエラーを恒久的に解決するには、ソースファイルを作成し、自動的に#define _CRT_SECURE_NO_WARNINGS 1を追加してください。