Реализация глобальной блокировки в Java

У меня относительно простой (возможно, глупый) вопрос по поводу синхронизации в Java.

У меня есть блоки синхронизации, которые блокируют различные объекты в моем коде. В некоторых сценариях я хочу получить глобальную блокировку, которая включает в себя все остальные операторы синхронизации в моем коде.

Есть ли причудливый способ сделать это на Java, не переписывая весь текущий код синхронизации?

Например,

Нить т1

synchronized (o1)
{
    synchronized (o2)
    {
        // ...
    }
}

Резьба т2

synchronized (global_lock)
{
    // ...
}

Когда поток t2 находится внутри синхронизированного блока, поток t1 не должен получать блокировки на o1 и o2.

Большое спасибо, если


person Community    schedule 07.06.2009    source источник
comment
глобальная блокировка звучит как очень плохая идея.....   -  person Mitch Wheat    schedule 07.06.2009
comment
Вы правы, это вообще плохая идея. Мне это нужно для того, что я реализую, к сожалению. Я подозреваю, что мог бы каким-то образом использовать пакет java.util.concurrent, но мне нужно было бы переписать синхронизированные блоки; лучше бы этого не делал! :)   -  person    schedule 07.06.2009
comment
Почему вы не хотите перезаписывать синхронизированные блоки? Если вы боитесь, что ваш код сломается, я рекомендую прочитать о параллелизме (JCiP — хорошая книга) и вернуть контроль над своим кодом.   -  person Chris Vest    schedule 07.06.2009
comment
Не вдаваясь в подробности, я использую типы владения, чтобы вывести необходимые блокировки для определенных блоков кода. В некоторых случаях мы не уверены, какие объекты являются псевдонимами, и поэтому нам необходимо обеспечить чрезмерно консервативную блокировку. Чтобы сделать это правильно, нам потребуется внутрипроцедурный анализ для определения набора точек для каждой переменной. Вместо этого, чтобы сэкономить время, мы планируем получить глобальную блокировку, когда возможно, что определенные типы переменных, принадлежащих нам, могут быть псевдонимами в определенном блоке кода. Я надеялся, что мне не придется менять текущую синхронизированную генерацию кода из-за времени :)   -  person    schedule 07.06.2009


Ответы (3)


  1. Это невозможно;
  2. Это действительно плохая идея (извините).

Он подвержен взаимоблокировкам, поскольку вынуждает вас иметь заранее определенный порядок блокировки для всех блокировок, независимо от того, где они находятся.

Обычно неплохо, если вам нужно приобрести два замка, всегда иметь заранее определенный порядок:

synchronized(LOCK1) {
  synchronized(LOCK2) {

  }
}

Но для глобальной блокировки потребуется какой-то протокол — глобальный порядок приобретения — для всех замков. А это может быть вообще невозможно. Большинство замков охраняют определенные, автономные, критические разделы. Они не будут знать, что кто-то их «вытащит» и получит, и поэтому не будут написаны для решения этой ситуации.

Так что это невозможно, и вы должны быть счастливы, что это не так. Хотя это кажется легким выходом, он принесет много боли.

person Robert Munteanu    schedule 07.06.2009
comment
Вау, не могу поверить, что этот вопрос был задан так давно. Глобальная блокировка является одной из самых фундаментальных потребностей в CEP (обработка сложных событий). Коммерческие продукты, такие как бизнес-события tibco, имеют встроенную поддержку таких функций. И да, когда вам нужно получить несколько замков, сортировка их в одном и том же порядке является обязательной. Я пришел к этому вопросу, потому что мне нужно делать подобные вещи, используя общий подход, без специальной/коммерческой поддержки инструментов. - person ric; 11.12.2020

Оставив в стороне явный ужас того, что вы предлагаете, вы можете рассмотреть возможность использования аспектно-ориентированного программирования (АОП) для «вплетения» дополнительной синхронизации/блокировки в ваш код во время выполнения. Вы должны быть в состоянии сделать это, не записывая исходный код.

Существует множество вариантов AOP, включая AspectJ и Spring AOP, которые могут подойти в зависимости от вашей среды.

person skaffman    schedule 07.06.2009

Единственный возможный способ сделать это — разобрать/изменить/сохранить (автоматически) весь код. Недавно я сделал что-то подобное для проекта, и это сработало довольно хорошо. Можем поговорить еще, если интересно.

person Mihai Toader    schedule 07.06.2009