2012-04-13 61 views
1

.NETミューテックスが待ちスレッドの1つにAbandonedMutexExceptionを投げない、またはMutex.Dispose()が呼び出されたときにミューテックスを解放しない理由を理解できません。なぜ.NETのミューテックスは破棄されたときにAbandonedMutexExceptionをスローしませんか?

特に

、このようなコードはデッドロックします:

public static void testCall() 
{ 
    using (var mutex = new System.Threading.Mutex(false, "testname")) 
    { 
     mutex.WaitOne(); 
     Console.WriteLine("second call"); 
    } 
} 

public static void Main(string[] args) 
{ 
    var thread = new System.Threading.Thread(testCall); 
    using (var mutex = new System.Threading.Mutex(false, "testname")) 
    { 
     mutex.WaitOne(); 
     Console.WriteLine("first call"); 
     thread.Start(); 
     System.Threading.Thread.Sleep(new TimeSpan(0, 0, 5)); 
     Console.WriteLine("sleep done"); 
    } 

    thread.Join(); 
} 

マインドあなたは、私がAbandonedMutexExceptionを理解し、通常は所有しているスレッドが死ぬ場合にのみトリガーされる基本的なWIN32ミューテックスから来て、ネイティブコードで - I長い間C/C++コードを書いており、基礎をなすデザインを十分に認識しています。私はまた、次のコードは、簡単な回避策であることを知っている:

using (var mutex = new System.Threading.Mutex(false, "testname")) 
{ 
    mutex.WaitOne(); 
    try 
    { 
     Console.WriteLine("first call"); 
     thread.Start(); 
     System.Threading.Thread.Sleep(new TimeSpan(0, 0, 1)); 
     Console.WriteLine("sleep done"); 
    } 
    finally 
    { 
     mutex.ReleaseMutex(); 
    } 
} 

私は理解していないことは、オブジェクトが明示的にロックを保持している間に処分されたときのリリースを強制しませ.NETのミューテックスの理論的根拠です。それは.NETプログラミングのパラダイムの他の部分とよりインラインではないでしょうか?開発者がロックされたmutexを明示的に破棄した場合、それを放棄したものとしてマークするだけです。

答えて

2

おそらく、あなたが提案する方法では動作しないようにしてください。

using (var m = new Mutex(....)) 
{ 
    m.WaitOne(); 
    // do some stuff here 
    // that ends up throwing an exception 
} 

スレッドがmutexを保持している間は例外がスローされます。ミューテックスが処分の一部として解放された場合、他のスレッドはミューテックスを取得し、更新しているデータでパーティーを開始する可能性があります。それ以外は、データが未知(おそらく矛盾しているか壊れている)の状態になっています。

例外を処理してクリーンアップするのが最善ですが、ミューテックスを取得しようとする次のスレッドが知っているように、むしろミューテックスが保持されたままになっている(またはスレッドが死ぬと放棄される)何か悪いことが起こった。

上記に加えて、自動リリースを追加するには、.NETラッパーがどのスレッドがそのミューテックスを所有しているかを追跡する必要があります。そして、メソッドは、ReleaseMutexを呼び出すべきかどうかを決定するためにその値をチェックする必要があります。そして、それを追跡することはできません。 .NETプログラムは、ラッパーの知識なしにミューテックスを取得または解放することができる、いくつかのアンマネージドコードにミューテックスハンドルを渡すことができます。

答えは二倍です。まずは不可能です。第二に、たとえ可能であったとしても、あなたはおそらくその行動を望んでいません。

+0

私は同意しません。コードが例外を処理しない場合、ミューテックスをロックしたコードが意図しない動作(例外)によって失われたため、適切な動作は 'AbandonedMutexException'をスローすることです。私は、 'ReleaseMutex()'は賢明ではないことに気付いていますが、 'AbandonedMutexException'は意味があります。 –

+0

しかし、スレッドが終了しなければ、ミューテックスは放棄されません。 –

+0

いいえ、放棄されたWIN32の意味ではありませんが、例外がスローされ、処理されなかった場合はあなたの例では言いません*と*ミューテックスは破棄されます。 " –

関連する問題