Monitor.Enter()によって排他的にロックされたオブジェクトの参照を変更した場合、予想通り、SynchronizationLockExceptionがスローされました。しかし、例外がスローされる前に、いくつかのスレッドがMonitorを通過するのを見て驚いた。ロックされたオブジェクトを排他的に変更するときの変な動作 - Monitor.Enter(x)
以下のコードは次のとおりです。
- 100件のスレッド
- を作成して開始しManualResetEventが設定されるまで、すべてのスレッドを待機させます。
- ManualResetEvent - Indyレースで緑色の旗を振るようなものを設定します。
- 排他ロック(Monitor.Enter(x))をx
- xの参照に設定します。
この時点で、何らかの例外がスローされると予想しましたが、Monitor.Exit(x)までは発生しません。本当に奇妙なのは、例外が発生する前に10〜20のスレッドがロックを越えることができるように見えることです。それはどうですか?それはそうではないように思われます。もちろん、排他的にロックされたオブジェクトの参照を変更することは、いいえです。私は実際のコードでは決してしませんでしたが、他のスレッドがモニターを過ぎているのを見て驚いていました。あなたの考え?
using System;
using System.Threading;
namespace ThreadingPlayground
{
class Program
{
private int _value;
object x = new object();
ManualResetEvent _event = new ManualResetEvent(false);
static void Main()
{
Program p = new Program();
p.StartThreads();
Console.ReadLine();
}
private void StartThreads()
{
for(int i = 0;i<100;i++)
{
Thread t = new Thread(IncrementValue);
t.Start();
}
_event.Set();
}
private void IncrementValue()
{
WaitHandle.WaitAll(new WaitHandle[] {_event});
Monitor.Enter(x);
// Change the reference of the exclusively locked object. This
// allows other threads to enter, should this be possible?
x = Thread.CurrentThread.ManagedThreadId.ToString();
Console.WriteLine(++_value);
// throws a SynchronizationLockException
// but not until 10 - 20 more lines are written
Monitor.Exit(x);
}
}
}
ので変更Monitor.Enter()に渡される変数の参照は、ロックを解除するようなものです。まあ、Monitor.Endで例外がスローされる以外は例外です。それは理にかなっている。ありがとうございました。理由はわかりませんが、ロックされた変数への参照を変更するとすぐに例外がスローされると思っていました。 –
いいえ、あなたはロックを解除していません。それを次のように考えてください。あなたはあなたの家に戸を閉じ込めました。あなたは大工を連れて来てドアを全部交換しました。新しいドアがロックされていないときにあなたは驚いた: – bdonlan
Behaiorallyおそらくそれのようですが、それは実際にそれをやっていません。他のスレッドがロックしようとするオブジェクトの参照を変更するだけです。 –