Приоритетность приобретения справедливого ReentrantLock, где он потенциально может быть заблокирован

У меня есть ReentrantLock, на котором блокируется множество операций, который был создан с помощью new ReentrantLock(true). Есть ли способ для потока «вторгнуться» в блокировку и получить ее после того, как она будет выпущена, но до любых других потоков?

Я рассмотрел различные комбинации синхронизированного и неметрированного tryLock:

  • tryLock() сам по себе будет вторгаться в блокировку, если она уже разблокирована и потоки ожидают, но не будут ждать, пока блокировка станет доступной.
  • Тот же метод с тайм-аутом справедлив.
  • Объединение обоих не сработает, поскольку, если он заблокирован в начале, tryLock, основанный на тайм-ауте, вернется к справедливому планированию.

Или я не прав?


person nanofarad    schedule 02.12.2013    source источник
comment
Вы видели это?   -  person Domi    schedule 03.12.2013
comment
@ Доми, мне нужно посмотреть. Вчера я переделал свой код, чтобы обеспечить безблокировочные операции с приоритетом, но такая ситуация, скорее всего, появится снова.   -  person nanofarad    schedule 03.12.2013


Ответы (1)


Как видите, здесь, ReentrantLock использует _ 2_ как фактическая реализация очереди потоков. Видя, что ни один из его методов не может быть переопределен, вы не можете сделать это легко, то есть заменить стандартную очередь потоков на приоритетную очередь.

Но, как говорится в документации: «Этот класс обеспечивает эффективную и масштабируемую основу для синхронизации, частично за счет специализации диапазона его использования для синхронизаторов, которые могут полагаться на состояние int, параметры получения и выпуска, а также внутреннюю очередь ожидания FIFO. Когда этого недостаточно, вы можете создавать синхронизаторы на более низком уровне, используя атомарные классы, ваши собственные классы java.util.Queue и поддержку блокировки LockSupport ».

Вот что вам нужно сделать: построить свой собственный замок. Ваша основная цель - позволить методу release использовать очередь приоритетов для принятия решения. Если производительность не является проблемой, вы можете просто использовать стандартный PriorityQueue, где вы можете просто сделать его чтение и запись потокобезопасным с помощью synchronized, ReentrantLock или любой другой доступной стандартной блокировки. Трудно найти потокобезопасные очереди с приоритетом. Однако, если производительность важна, этот документ из 2003 года может быть вам интересен.

Однако, поскольку пользователь может изменить приоритет потока в любой момент времени, проще всего использовать базовую очередь и использовать стабильная сортировка (чтобы не нарушить порядок потоков с равным приоритетом) до перехода к следующему парню. Конечно, производительность будет плохой, если вы захотите использовать ее для критических разделов с высокой конкуренцией.

person Domi    schedule 03.12.2013
comment
Доми: Я не ищу очередь с полным приоритетом. Я ищу просто какое-то единственное переопределение, а не настраиваемые уровни приоритета. Думаю, мне придется заново реализовать. - person nanofarad; 03.12.2013
comment
@hexafraction Как я уже сказал, просто используйте стандартный PriorityQueue. Самая простая реализация блокировки на самом деле довольно проста (вы можете просто использовать ReentrantLock или другую блокировку для блокировки очереди при доступе к ней). - person Domi; 03.12.2013
comment
@hexafraction Я добавил еще один абзац, на случай, если вы хотите поддержать его для работы с Thread.setPriority. - person Domi; 03.12.2013