Я хотел посмотреть, что произойдет, если вы измените ссылку на объект, заблокированный исключительно Monitor.Enter (). Как и ожидалось, было сгенерировано исключение SynchronizationLockException. Но я был удивлен, увидев несколько потоков, проходящих мимо Монитора до того, как возникло исключение.
Вот что делает код ниже.
- создать и запустить 100 потоков
- заставляет весь поток ждать, пока не будет установлено ManualResetEvent.
- установить ManualResetEvent - Вроде как размахивать зеленым флагом на гонке Инди.
- установить эксклюзивную блокировку (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);
}
}
}