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

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

29.12.2013, 22:11. Показов 2441. Ответов 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
Ответ Создать тему
Новые блоги и статьи
Функция установки текстового статуса в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
К слову об оптимизации
kumehtar 01.04.2026
Вспоминаю начало 2000-х, университет, когда я писал на Delphi. Тогда среди программистов на форумах активно обсуждали аккуратную работу с памятью: нужно было следить за переменными, вовремя. . .
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
Модель здравосоХранения 6. ESG-повестка и устойчивое развитие; углублённый анализ кадрового бренда
anaschu 31.03.2026
В прикрепленном документе раздумья о том, как можно поменять модель в будущем
10 пpимет, которые всегда сбываются
Maks 31.03.2026
1. Чтобы, наконец, пришла маршрутка, надо закурить. Если сигарета последняя, маршрутка придет еще до второй затяжки даже вопреки расписанию. 2. Нaдоели зима и снег? Не надо переезжать. Достаточно. . .
Перемещение выделенных строк ТЧ из одного документа в другой
Maks 31.03.2026
Реализация из решения ниже выполнена на примере нетипового документа "ВыдачаОборудованияНаСпецтехнику" с единственной табличной частью "ОборудованиеИКомплектующие" разработанного в конфигурации КА2. . . .
Functional First Web Framework Suave
DevAlt 30.03.2026
Sauve. IO Апнулись до NET10. Из зависимостей один пакет, работает одинаково хорошо как в режиме проекта так и в интерактивном режиме. из сложностей - чисто функциональный подход. Решил. . .
Автоматическое создание документа при проведении другого документа
Maks 29.03.2026
Реализация из решения ниже выполнена на нетиповых документах, разработанных в конфигурации КА2. Есть нетиповой документ "ЗаявкаНаРемонтСпецтехники" и нетиповой документ "ПланированиеСпецтехники". В. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru