ドキュメントに記載されているように、ミューテックスを所有していないスレッドがミューテックスを解放しようとしたため、ApplicationExceptionがスローされました。これは、ミューテックスがリリースされたことを意味するのではなく、ミューテックスをリリースしようとしたスレッドがミューテックスを所有していなかったことを意味します。
var mutex = new Mutex();
mutex.WaitOne();
var thread = new Thread(() =>
{
try
{
mutex.ReleaseMutex(); //This will throw ApplicationException
}
catch (ApplicationException ex)
{
Console.WriteLine("Failed to release mutex");
}
});
thread.Start();
thread.Join();
mutex.ReleaseMutex(); //No exception will be thrown here
この例では、最初のスレッドがミューテックスを作成して取得します。2番目のスレッドがスピンアップし、解放しようとして失敗します。失敗した後、所有しているスレッドはそれを解放します。
アップデート
前の質問では、そのコードを複数のスレッドで実行していること、および各スレッドに同じ競合状態が存在することに注意することが重要です。1つのスレッドがミューテックスを保持している間に、複数のスレッドがミューテックスの取得に失敗した可能性があるため、複数のスレッドも同様にミューテックスの解放に失敗します。例として、次の実行パスを取り上げます。
- スレッド1はミューテックスを取得します。
- スレッド1がミューテックスを持っているため、スレッド2はミューテックスの取得に失敗します。
- スレッド1がミューテックスを持っているため、スレッド3はミューテックスの取得に失敗します。
- スレッド3はミューテックスを解放しようとし、ミューテックスを所有していないため、ApplicationExceptionをスローします。
- スレッド1はミューテックスを解放します。
- スレッド2はミューテックスを解放しようとし、ミューテックスを所有していないため、ApplicationExceptionをスローします。
ミューテックスの解放に失敗したときにスレッド3が爆発したという事実は、スレッド2も同じことを実行して爆発したという事実とは相関関係がありません。