Форум программистов, компьютерный форум, киберфорум
Java
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.91/11: Рейтинг темы: голосов - 11, средняя оценка - 4.91
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705

Почему происходит взаимная блокировка потоков?

29.12.2013, 22:11. Показов 2425. Ответов 5
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Код из Гербердта Шилдта, глава 11, класс Deadlock
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// An example of deadlock.
class A {
  synchronized void foo(B b) {
    String name = Thread.currentThread().getName();
 
    System.out.println(name + " entered A.foo");
 
    try {
      Thread.sleep(1000);
    } catch(Exception e) {
      System.out.println("A Interrupted");
    }
 
    System.out.println(name + " trying to call B.last()");
    b.last();
  }
 
  synchronized void last() {
    System.out.println("Inside A.last");
  }
}
 
class B {
  synchronized void bar(A a) {
    String name = Thread.currentThread().getName();
    System.out.println(name + " entered B.bar");
 
    try {
      Thread.sleep(1000);
    } catch(Exception e) {
      System.out.println("B Interrupted");
    }
 
    System.out.println(name + " trying to call A.last()");
    a.last();
  }
 
  synchronized void last() {
    System.out.println("Inside A.last");
  }
}
 
class Deadlock implements Runnable {
  A a = new A();
  B b = new B();
 
  Deadlock() {
    Thread.currentThread().setName("MainThread");
    Thread t = new Thread(this, "RacingThread");
    t.start();
 
    a.foo(b); // get lock on a in this thread.
    System.out.println("Back in main thread");
  }
 
  public void run() {
    b.bar(a); // get lock on b in other thread.
    System.out.println("Back in other thread");
  }
 
  public static void main(String args[]) {
    new Deadlock();
  }
}
Bash
1
2
3
4
MainThread entered A.foo
RacingThread entered B.bar
MainThread trying to call B.last()
RacingThread trying to call A.last()
Моё видение ситуации в корне отличается от Шилдтовского. Я думаю, что НИЧЕГО не мешает исполниться как методу B.last, так и методу A.last. Почему они не исполняются- непонятно. Почему же? Спасибо, кто откликнется.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
29.12.2013, 22:11
Ответы с готовыми решениями:

Почему происходит зацикливание??
Я создаю метод для последовательного поиска и удаления в хеш таблице. У меня есть массив nonEmpty,где все значения boolean. Там хранятся...

Не срабатывает взаимная блокировка
Изучаю многопоточность при запуски данного кода, всегда выводится два потока, компилятор никогда не блокируется,

Многопоточность Java (Взаимная блокировка)
Есть пример public class Student { private ArrayList friends = new ArrayList(); public synchronized ArrayList getFriends() ...

5
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
29.12.2013, 23:03
Цитата Сообщение от kravam Посмотреть сообщение
Я думаю, что НИЧЕГО не мешает исполниться как методу B.last, так и методу A.last
Методу B.last, чтобы выполнится необходимо захватить монитор на объекте b(об этом указываем модификатор synchronized). Однако, монитор на объекте b захвачен другим потоком.
Ситуация с методом A.last аналогична.
0
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
29.12.2013, 23:19  [ТС]
Я правильно понял, что (допустим имеем такой псевдокод):

Java
1
2
3
4
class B {
  synchronized void foo() {while (true);};
  synchronized void bar();
}
Если как-то где-то кем-то выполняется метод B.foo, то, пока он не выполнится, метод B.bar выполняться БЕЗУСЛОВНО не будет?
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
30.12.2013, 09:06
Да, примерно так.
Одно только уточнение: один и тот же поток, может захватывать монитор несколько раз.
То есть, если вы внутри foo вызовите bar, он вызовется без проблем.
0
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
30.12.2013, 23:58  [ТС]
Что ж, неплохое синтаксическое решение. Тем более, то оно позволяет сократить такой вариант:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Q {
  int n;
  boolean valueSet = false;
 
  synchronized int get() {
    while(!valueSet)
      try {
        wait();
 
      } catch(InterruptedException e) {
        System.out.println("InterruptedException caught");
      }
 
      System.out.println("Got: " + n);
      valueSet = false;
      notify();
      return n;
  }
 
  synchronized void put(int n) {
    while(valueSet)
      try {
        wait();
      } catch(InterruptedException e) {
        System.out.println("InterruptedException caught");
      }
 
      this.n = n;
      valueSet = true;
      System.out.println("Put: " + n);
      notify();
  }
}
До такого:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Q {
  int n;
  boolean valueSet = false;
 
  synchronized int get() {
      if (valueSet)
      System.out.println("Got: " + n);
      valueSet= false; 
      return n;
  }
 
  synchronized void put(int n) {
      if (!valueSet)
      this.n = n;
      System.out.println("Put: " + n);
      valueSet= true;
      }
}
БЕЗ какой-либо потери качества. Первый вариант Шилдта, второй мой. Шилдт откровенно в нём перемудрил. Если бы не ключевое слово "synchronized", то без wait() и notify() было бы не обойтись (и то, put адо было бы переписать как:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    
  synchronized void put(int n) {
 while(valueSet)
      try {
        wait();
      } catch(InterruptedException e) {
        System.out.println("InterruptedException caught");
      }
 
      this.n = n;
      System.out.println("Put: " + n);
      valueSet = true;
      notify();
  }
)
А так вполне себе.


полностью код Шилдта, кому интересно
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// A correct implementation of a producer and consumer.
class Q {
  int n;
  boolean valueSet = false;
 
  synchronized int get() {
    while(!valueSet)
      try {
        wait();
 
      } catch(InterruptedException e) {
        System.out.println("InterruptedException caught");
      }
 
      System.out.println("Got: " + n);
      valueSet = false;
      notify();
      return n;
  }
 
  synchronized void put(int n) {
    while(valueSet)
      try {
        wait();
      } catch(InterruptedException e) {
        System.out.println("InterruptedException caught");
      }
 
      this.n = n;
      System.out.println("Put: " + n);
      valueSet = true;
      notify();
  }
}
 
class Producer implements Runnable {
  Q q;
 
  Producer(Q q) {
    this.q = q;
    new Thread(this, "Producer").start();
  }
 
  public void run() {
    int i = 0;
 
    while(true) {
      q.put(i++);
    }
  }
}
 
class Consumer implements Runnable {
  Q q;
 
  Consumer(Q q) {
    this.q = q;
    new Thread(this, "Consumer").start();
  }
 
  public void run() {
    while(true) {
      q.get();
    }
  }
}
 
class PCFixed {
  public static void main(String args[]) {
    Q q = new Q();
    new Producer(q);
    new Consumer(q);
 
    System.out.println("Press Control-C to stop.");
  }
}
0
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
09.01.2014, 00:35  [ТС]
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  synchronized int get() {
      if (valueSet) {
       System.out.println("Got: " + n);
       valueSet= false; 
      }
      return n;
  }
 
  synchronized void put(int n) {
      if (!valueSet) {
       this.n = n;
       System.out.println("Put: " + n);
       valueSet= true;
      }  
  }
Исправил фигурные скобки.

...Но, конечно, этот код несостоятельный, я ошибся, приняв его за верный. Взять, к примеру, поток Producer. Он сконструирован так, что при проверке в функции put переменной valueSet на истиность, если проверка не пройдёт, то поток выходит из функции put и снова вызывает её же в бесконечном цикле, УВЕЛИЧИВАЯ переменную i. Таким образом, она увеличивается как бы вхолостую, что неправильно. Избежать этого можно, если заставить Producer оставаться в функции put, если valueSet не проходит проверку на истиность. Для этого надо задействовать wait.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
09.01.2014, 00:35
Помогаю со студенческими работами здесь

Блокировка потоков при массовой рассылке сообщений
Привет! Пишу серверный чат на сокетах. Все пользователи находятся в общем пространстве. Столкнулся с такой проблемой, что при рассылке...

Происходит ли блокировка объекта при использовании synchronized() метода?
Добрый день. Понятно, что при инициализации synchronized() блока в качестве параметра ему передается объект, методы которого необходимо...

Почему происходит блокировка потоков в приведенном коде
Здравствуйте. Есть метод run. Создаются и запускаются 2 потока для вызова этого метода. По моему разумению потоки дойдя до первой 1000...

Взаимная блокировка потоков
В одной из моих программ, наблюдается взаимная блокировка потоков. Судя по всему это происходит из-за обращения к SysListView32 из...

Взаимная блокировка транзакций
Здравствуйте! Можно ли каким-либо образом на одном компьютере запустить две транзакции, которые будут блокировать друг друга?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru