Информация об изменениях

Сообщение Re[4]: Двойная блокировка переключатель от 22.09.2015 13:03

Изменено 22.09.2015 13:58 igor-booch

опишу задачу по другому, конкретно что нужно:

Есть два ресурса (объекта) A и B.
Есть потоки которые всегда захватывают сначала A, а потом B. Это потоки типа N.
Есть потоки которые захватывают только B. Это потоки типа M.
Если пользоваться обычным обычным Monitor'ом, то получается следующее.

1) Поток I типа N захватывает ресурс A.
2) Теперь потоку I требуется переключиться на блокировку ресурса B. Для этого
2.1) Поток I освобождает ресурс А
2.2) Поток I захватывает ресурс B

Существует вероятность, что между пунктами 2.1 и 2.2 вклинится другой поток типа N и также захватит сначала A, потом B. Это недопустимо. Освобождение и захват должны быть атомарными операциями.
Кажется что можно поменять пункты 2.1 и 2.2 местами, то есть сначала захватывать B, а потом освобождать A. Но на сцену выходят потоки типа M. Поток типа M может захватить B, до захвата потоком I типа N блокировки B и тогда A не освободится до освобождения потоком типа M блокировки B, что недопустимо. Допустимо, если поток I типа N переключится на блокировку B, и подождет пока её освободит поток типа M. При этом во время ожидания блокировка A будет свободна.

Я вижу пока только один способ, также пользуемся обычным обычным Monitor'ом но по-другому

1) Поток типа N захватывает ресурс A.
2) Теперь потоку I требуется переключиться на блокировку ресурса B. Для этого
2.1) Поток I запускает дополнительный поток III. В этом потоке сначала захватывается B, потом выполняется код, который поток I типа N хотел выполнить после переключения на блокировку ресурса B.
2.2) Поток I освобождает ресурс A
2.3) Поток I ждёт завершения потока III (.Join)

Хочется без создания дополнительных потоков. Может что-то с низкоуровневым примитивами синхронизации можно что-то замутить, может ReaderWriterLock как-то использовать
опишу задачу по другому, конкретно что нужно:

Есть два ресурса (объекта) A и B.
Есть потоки которые всегда захватывают сначала A, а потом B. Это потоки типа N.
Есть потоки которые захватывают только B. Это потоки типа M.
Если пользоваться обычным обычным Monitor'ом, то получается следующее.

1) Поток I типа N захватывает ресурс A.
2) Теперь потоку I требуется переключиться на блокировку ресурса B. Для этого
2.1) Поток I освобождает ресурс А
2.2) Поток I захватывает ресурс B

Существует вероятность, что между пунктами 2.1 и 2.2 вклинится другой поток типа N и также захватит сначала A, потом B. Это недопустимо. Освобождение и захват должны быть атомарной операцией.
Кажется что можно поменять пункты 2.1 и 2.2 местами, то есть сначала захватывать B, а потом освобождать A. Но на сцену выходят потоки типа M. Поток типа M может захватить B, до захвата потоком I типа N блокировки B и тогда A не освободится до освобождения потоком типа M блокировки B, что недопустимо. Допустимо, если поток I типа N переключится на блокировку B, и подождет пока её освободит поток типа M. При этом во время ожидания блокировка A будет свободна.

Я вижу пока только один способ, также пользуемся обычным обычным Monitor'ом но по-другому

1) Поток типа N захватывает ресурс A.
2) Теперь потоку I требуется переключиться на блокировку ресурса B. Для этого
2.1) Поток I запускает дополнительный поток III. В этом потоке сначала захватывается B, потом выполняется код, который поток I типа N хотел выполнить после переключения на блокировку ресурса B.
2.2) Поток I освобождает ресурс A
2.3) Поток I ждёт завершения потока III (.Join)

Хочется без создания дополнительных потоков. Может что-то с низкоуровневым примитивами синхронизации можно что-то замутить, может ReaderWriterLock как-то использовать