Когда несколько потоков запрашивают блокировку одного и того же объекта, гарантирует ли CLR, что блокировки будут получены в том порядке, в котором они были запрошены?
Я написал тест, чтобы проверить, было ли это правдой, и, похоже, укажите "да", но я не уверен, что это окончательно.
class LockSequence
{
private static readonly object _lock = new object();
private static DateTime _dueTime;
public static void Test()
{
var states = new List<State>();
_dueTime = DateTime.Now.AddSeconds(5);
for (int i = 0; i < 10; i++)
{
var state = new State {Index = i};
ThreadPool.QueueUserWorkItem(Go, state);
states.Add(state);
Thread.Sleep(100);
}
states.ForEach(s => s.Sync.WaitOne());
states.ForEach(s => s.Sync.Close());
}
private static void Go(object state)
{
var s = (State) state;
Console.WriteLine("Go entered: " + s.Index);
lock (_lock)
{
Console.WriteLine("{0,2} got lock", s.Index);
if (_dueTime > DateTime.Now)
{
var time = _dueTime - DateTime.Now;
Console.WriteLine("{0,2} sleeping for {1} ticks", s.Index, time.Ticks);
Thread.Sleep(time);
}
Console.WriteLine("{0,2} exiting lock", s.Index);
}
s.Sync.Set();
}
private class State
{
public int Index;
public readonly ManualResetEvent Sync = new ManualResetEvent(false);
}
}
Выводит:
Введено: 0
0 заблокировано
0 спит для 49979998 тиков
Введено: 1
Введено: 2
Введено: 3
Введено: 4
Введено: 5
Введено: 6
Введено: 7
Введено: 8
Перейти поступил:9
0 выход из блокировки
1 получил блокировку
1 спящий режим на 5001 тик
1 выход из блокировки
2 получил блокировку
2 спящий режим на 5001 тик
2 выход из блокировки
3 получил блокировку
3 спал 5001 тик
3 вышел из блокировки
4 получил блокировку
4 спал 5001 тик
4 вышел из блокировки
5 получил блокировку
5 спал 5001 тики
5 выход из блокировки
6 блокировка
6 выход из блокировки
7 блокировка
7 выход из блокировки
8 блокировка
8 выход из блокировки
9 блокировка
9 блокировка выхода