S>В этот момент у потоков N1 и N2 равные шансы захватить B. Это означает, что с вероятностью 50% произойдёт сценарий вклинивания N2 внутрь транзакции, выполняемой N1, что по вашему второму требованию запрещено.
Вот и не должны быть равные шансы. Приоритет должен быть отдан N1, а N2 должен встать в очередь, так как N1 захватил A раньше, чем N2. Кто первым захватывает A, тот первым захватывает B. Вопрос топика как это реализовать?
IB>>Я вижу пока только один способ, также пользуемся обычным обычным Monitor'ом но по-другому
IB>>1) Поток I типа N захватывает ресурс A.
IB>>2) Теперь потоку I требуется переключиться на блокировку ресурса B. Для этого
IB>> 2.1) Поток I запускает дополнительный поток III. В этом потоке сначала захватывается B, потом выполняется код, который поток I хотел выполнить после переключения на блокировку ресурса B.
IB>> 2.2) Поток I освобождает ресурс A
IB>> 2.3) Поток I ждёт завершения потока III (.Join)
S>Вы же понимаете, что порядок выполнения 2.1 и 2.2 ничем не гарантирован? Т.е. поток I может освободить ресурс А задолго до того, как III захватит B. Поэтому функционально это решение эквивалентно неатомарному освобождению А, а затем захвату B.
Да это проблема, согласен
перед пунктом 2.2 думал покрутиться в цикле
while (thread.ThreadState == ThreadState.Unstarted) {}
Но это тоже не даёт гарантии.
Thread.MemoryBarrier не знаю, может ли помочь в этом случае
Вот и вопрос. Как гарантировать, что B будет захвачена в дополнительном потоке III (п. 2.1), раньше чем освободится A (п. 2.2)?
IB>>Хочется без создания дополнительных потоков. Может что-то с низкоуровневым примитивами синхронизации можно что-то замутить, может ReaderWriterLock как-то использовать
S>Я всё ещё не понимаю природы ваших ограничений. На первый взгляд, задача решается в том случае, если доступ к B будет рулиться не монитором, а очередью — чтобы гарантировать, что потоки получают доступ к B в том же порядке, как они получали доступ к А.
Спасибо, возможно это и есть решение: заюзать очередь и синхронизировать Monitor'ом добавление в неё Action'ов, которые должны выполняться либо в блокировке A, либо в блокировке B