Вопрос о ситуации с мертвой блокировкой в Java

Двоичный поиск используется везде . Возьмите любой отсортированный набор из любой библиотеки языка (Java.NET, C++ STL и так далее), и они все будут использовать (или иметь опцию использовать), двоичный поиск для нахождения значений. В то время как верный, что необходимо редко реализовывать его, все еще необходимо понять принципы позади него для использования в своих интересах его.

11
задан Saobi 13 October 2009 в 20:23
поделиться

6 ответов

Следует отметить один важный момент: блокируются не методы , а экземпляры объектов .

Когда вы вызываете alphonse.bow (gaston) , он пытается получить блокировку на alphonse . Получив блокировку, он печатает сообщение и вызывает gaston.bowBack (alphonse) . В этот момент он пытается получить блокировку на Gaston . Как только блокировка установлена, он печатает сообщение, затем снимает блокировку и, наконец, снимает блокировку на alphonse .

В тупиковой ситуации блокировки устанавливаются в таком порядке, что нет возможности для любой поток для продолжения.

  • Поток 1: получает блокировку на alphonse
  • Поток 2: получает блокировку на gaston
  • Поток 1: печатает сообщение
  • Тема 1: пытается получить блокировку на gaston - не может, потому что поток 2 уже имеет это.
  • поток 2: выводит сообщение
  • поток 2: пытается получить блокировку на alphonse - не может, потому что он уже есть в потоке 1.
27
ответ дан 3 December 2019 в 02:11
поделиться

Альфонс и Гастон - два разных объекта. Каждый объект имеет встроенный монитор (блокировку), связанный с ним.

Это может произойти следующим образом:

alphonse создан. Его объектный монитор - 1.

Гастон создан. Его объектный монитор - 2.

alphonse.bow (gaston); Альфонсу теперь принадлежит замок №1

gaston.bow (alphonse); Гастон теперь владеет замком №2

Альфонс поклоняется Гастону и ждет шлюза №2 Гастон выкрикивает поклон. Назад на Альфонса и ждет блокировки №1

Разумный? Использование синхронизированных ключевых слов блокирует, которые экземпляры отслеживают на протяжении всего метода. Пример можно переписать следующим образом:

public class Deadlock {
    static class Friend {
        private final String name;
        public Friend(String name) {
            this.name = name;
        }
        public String getName() {
            return this.name;
        }
        public void bow(Friend bower) {
            synchronized(this) {            
                        System.out.format("%s: %s has bowed to me!%n", 
                    this.name, bower.getName());
                        bower.bowBack(this);
            }
        }
        public void bowBack(Friend bower) {
            synchronized(this) {
                        System.out.format("%s: %s has bowed back to me!%n",
                    this.name, bower.getName());
            }
        }
    }
}
8
ответ дан 3 December 2019 в 02:11
поделиться

Блокировки удерживаются на объектах Java, а не на методах java. Таким образом, когда метод synchronized используется для метода, он блокирует объект «this». В случае статического метода он блокирует объект класса.

Вы можете явно указать объект монитора, используя synchronized (object) {}

1
ответ дан 3 December 2019 в 02:11
поделиться

Чтобы добавить к simonn, et al.,

Если вы хотите визуализировать это, скомпилируйте и запустите программу и сгенерируйте дамп потока работающей программы. Вы можете сделать это, набрав Ctrl - Break в консоли Windows или выполнив команду kill -QUIT [pid] в системе * nix. Это предоставит вам список всех потоков , запущенных в вашей системе, и где они либо выполняются, либо ожидают, а также мониторы, которые потоки либо блокируются, либо ожидают блокировки.

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

   new Thread(new Runnable() {
        public void run() { alphonse.bow(gaston); }
    }, "Alphonse").start();
    new Thread(new Runnable() {
        public void run() { gaston.bow(alphonse); }
    }, "Gaston").start();
1
ответ дан 3 December 2019 в 02:11
поделиться

synchronized в определении метода - это сокращение для синхронизации самого объекта (this). По сути, это означает, что bow () и bowBack () не могут быть вызваны для одного объекта Friend одновременно.

Теперь, если оба Friends попадают в bow (), ни один из них не сможет вызвать метод bowBack () друг друга.

0
ответ дан 3 December 2019 в 02:11
поделиться

Мне пришлось бы дважды проверить, но я думаю, что синхронизированный метод блокирует объект класса, поэтому он блокирует другие синхронизированные методы в том же классе.

Я думаю, что он блокируется. сам объект класса, поэтому он даже блокирует различные экземпляры.

Отредактируйте, чтобы добавить:

Взгляните на эту часть спецификации языка Java

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

-3
ответ дан 3 December 2019 в 02:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: