С Новым годом! Форум программистов, компьютерный форум, киберфорум
Java SE (J2SE)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.81/21: Рейтинг темы: голосов - 21, средняя оценка - 4.81
2 / 2 / 0
Регистрация: 22.11.2013
Сообщений: 101

Обедающие философы, уменьшить возможность возникновения deadlock-а

07.10.2016, 12:54. Показов 4342. Ответов 11
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть программа, которая решает задачу обедающих философов.
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
77
78
79
80
81
82
83
84
85
public class Phil {
    int pos; 
      Fork left; 
      Fork right; 
      int eatCount = 0; 
      long waitTime = 0; 
      long startWait; 
 
      Random rnd = new Random(); 
      public Phil (int pos, Fork left, Fork rigth){ 
      this.pos = pos; 
      this.left = left; 
      this.right = rigth; 
      } 
      
      public void eat(){ 
      waitTime+=System.currentTimeMillis()+startWait; 
      System.out.println("Философ "+pos+" ест"); 
      try{ 
       Thread.sleep(rnd.nextInt(100)); 
      } catch (InterruptedException e){ 
       e.printStackTrace(); 
      } 
      eatCount++; 
      System.out.println("Философ "+pos+" поел"); 
      } 
          public void think(){ 
       System.out.println("Философ "+pos+" думает"); 
       try{ 
        Thread.sleep(rnd.nextInt(100)); 
       } catch (InterruptedException e){ 
        e.printStackTrace(); 
       } 
       System.out.println("Философ "+pos+" проголодался"); 
       startWait=System.currentTimeMillis(); 
      }
}
 
public class MyPhil extends Phil implements Runnable { 
  volatile boolean stopFlag = false; 
  public MyPhil(int pos, Fork left, Fork rigth) { 
  super(pos, left, rigth); 
  } 
  
  public void run() { 
  while(!stopFlag){ 
   think(); 
   synchronized(left){ 
       } 
   synchronized(right){ 
 
     eat(); 
   } 
  } 
  System.out.println("Философ "+pos+" stop"); 
  } 
  
  public static void main(String[] args) throws Exception{ 
  int count = 5; 
  MyPhil[] phils = new MyPhil[count]; 
  Fork last = new Fork(); 
  Fork left = last; 
  for (int i=0; i<count; i++){ 
   Fork right=(i==count-1)? last: new Fork(); 
   phils[i] = new MyPhil (i,left,right); 
   left = right; 
  } 
  Thread[] threads = new Thread [count]; 
  for (int i=0; i<count; i++){ 
   threads[i] = new Thread (phils[i]); 
 
   threads[i].start(); 
  } 
  Thread.sleep(60000); 
  for (MyPhil phil: phils){ 
   phil.stopFlag = true; 
  } 
  for (Thread thread:threads){ 
   thread.join(); 
  } 
  for (MyPhil phil: phils){ 
   System.out.println("Философ "+phil.pos+" поел "+phil.eatCount+" раз и прождал "+phil.waitTime); 
   phil.stopFlag = true; 
  } 
  } }
Подскажите, пожалуйста, как можно оптимизировать этот код, чтобы уменьшить возможность возникновения ситуации deadlock(взаимная блокировка)?
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
07.10.2016, 12:54
Ответы с готовыми решениями:

Обедающие философы
Добрый вечер! Возник такой вот вопрос: Есть стандартная задача с обедающими философами, описанная в книге Таненбаума. Но...

Обедающие философы
Здравствуйте участники форума я на форуме нашел программу про обедающих философов вот её исходники using System; using...

Обедающие философы
Всем привет. Нужна помощь в решении задач об обедающих философах с помощью семафоров, мониторов и блокировки. Также нужно добавить главный...

11
 Аватар для HighPredator
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3
07.10.2016, 16:34
А в каком кейсе текущая имплементация позволяет схватить дедлок? Что-то из кода не пойму..
1
2 / 2 / 0
Регистрация: 22.11.2013
Сообщений: 101
09.10.2016, 14:36  [ТС]
Вероятность дедлока увеличивается, если в функциях eat и think убрать sleep(). Подскажите, пожалуйста, что нужно изменить?
0
 Аватар для HighPredator
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3
10.10.2016, 08:06
Ну я бы сделал так:
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
public class MyPhil extends Phil implements Runnable {
    private boolean stopFlag = false;
 
    private volatile Object volatileMutex;
 
    public MyPhil(int pos, Fork left, Fork right) {
        super(pos, left, right);
    }
 
    @Override
    public void run() {
        while (!getStopFlag()) {
            think();
            synchronized (left) {
            }
            synchronized (right) {
                eat();
            }
        }
        System.out.println("Философ " + pos + " stop");
    }
 
    public void stop() {
        synchronized (mutex()) {
            stopFlag = true;
        }
    }
 
    private boolean getStopFlag() {
        synchronized (mutex()) {
            return stopFlag;
        }
    }
 
    private Object mutex() {
        Object mutex = volatileMutex;
        if (mutex == null) {
            synchronized (this) {
                mutex = volatileMutex;
                if (mutex == null) {
                    mutex = new Object();
                    volatileMutex = mutex;
                }
            }
        }
        return mutex;
    }
}
1
2 / 2 / 0
Регистрация: 22.11.2013
Сообщений: 101
10.10.2016, 16:39  [ТС]
Спасибо огромное! А можете объяснить принцип работы private Object mutex()? Насколько я поняла, это взаимное исключение?
0
 Аватар для HighPredator
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3
10.10.2016, 16:53
Цитата Сообщение от Линда95 Посмотреть сообщение
это взаимное исключение?
Не понял, что вы под этим понимаете. Это специальный мьютекс -- объект по которому будет идти блокировка доступа. Он спроектирован так (сейчас могу неточно объяснить, ибо сам новичок в джаве, так что терминология достаточно новая), чтобы гарантировать детерминированное состояние в среде конкурентного доступа. На нем фиксируется монитор. Механизм работы в принципе вам станет ясен, если вы по шагам каждую инструкцию рассмотрите.
1
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
10.10.2016, 19:21
HighPredator, Зачем все эти пляски с ленивой инициализацией volatileMutex?
Обычно лок объявляют как
Java
1
private final Object mutext = new Object();
Вроде философ может есть только когда обе вилки у него, а у вас он одну отпускает, перед тем как взяться за вторую. synchronized (left) и synchronized (right) должны быть вложены друг в друга.
1
 Аватар для HighPredator
6045 / 2160 / 753
Регистрация: 10.12.2010
Сообщений: 6,005
Записей в блоге: 3
10.10.2016, 23:03
Цитата Сообщение от turbanoff Посмотреть сообщение
Зачем все эти пляски с ленивой инициализацией volatileMutex?
Увидел у гугла, понравилось, пользую везде И это вроде не ленивая инициализация, а double-checking locking idiom если не ошибаюсь.
0
2 / 2 / 0
Регистрация: 22.11.2013
Сообщений: 101
11.10.2016, 18:23  [ТС]
Цитата Сообщение от turbanoff Посмотреть сообщение
synchronized (left) и synchronized (right) должны быть вложены друг в друга.
То есть должно получиться так?

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 public void run() {
        while (!getStopFlag()) {
            think();
            synchronized (left) {
                System.out.println("Философ "+pos+" левая вилка");
                synchronized (right) {
                System.out.println("Философ "+pos+" правая вилка");
                eat();
            }
            }
           
        }
        System.out.println("Философ " + pos + " stop");
    }
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
11.10.2016, 18:29
Линда95, да. eat можно вызывать только когда оба лока захвачены
Но, вот если так прямо сделать - то в вашем коде будет возможен deadlock.
Нужно хитро захватывать локи, чтобы такого не было.
1
2 / 2 / 0
Регистрация: 22.11.2013
Сообщений: 101
12.10.2016, 19:31  [ТС]
Цитата Сообщение от turbanoff Посмотреть сообщение
Нужно хитро захватывать локи, чтобы такого не было.
А каким образом это можно сделать, не подскажете?
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
12.10.2016, 21:29
Лучший ответ Сообщение было отмечено turbanoff как решение

Решение

На википедии описаны возможные решения - https://ru.wikipedia.org/wiki/Проблема_обедающих_философов
Вот решение с официантом:
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
class Fork {
}
 
class Waiter {
    private final Set<Fork> usedForks = Collections.newSetFromMap(new IdentityHashMap<>());
 
    void letMeEat(Fork a, Fork b, Runnable eat) {
        synchronized (usedForks) {
            while (usedForks.contains(a) || usedForks.contains(b)) {
                try {
                    usedForks.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            usedForks.add(a);
            usedForks.add(b);
        }
        synchronized (a) {
            synchronized (b) {
                eat.run();
            }
        }
        synchronized (usedForks) {
            usedForks.remove(a);
            usedForks.remove(b);
            usedForks.notifyAll();
        }
    }
}
 
class MyPhil implements Runnable {
    volatile boolean stopFlag = false;
    int pos;
    Fork left;
    Fork right;
    private final Waiter waiter;
    int eatCount = 0;
    long waitTime = 0;
    long startWait;
    Random rnd = new Random();
 
    public MyPhil(int pos, Fork left, Fork right, Waiter waiter) {
        this.pos = pos;
        this.left = left;
        this.right = right;
        this.waiter = waiter;
    }
 
    public void run() {
        while (!stopFlag) {
            think();
            waiter.letMeEat(left, right, () -> {
                if (Thread.holdsLock(left) && Thread.holdsLock(right)) {
                    eat();
                } else {
                    throw new RuntimeException("Waiter is a liar!");
                }
            });
        }
        System.out.println("Философ " + pos + " stop");
    }
 
    public static void main(String[] args) throws Exception {
        int count = 5;
        Fork[] forks = new Fork[count];
        for (int i = 0; i < forks.length; i++) {
            forks[i] = new Fork();
        }
        MyPhil[] phils = new MyPhil[count];
        Waiter waiter = new Waiter();
        for (int i = 0; i < count; i++) {
            Fork left = forks[i];
            Fork right = (i == count - 1) ? forks[0] : forks[i + 1];
            phils[i] = new MyPhil(i, left, right, waiter);
        }
        Thread[] threads = new Thread[count];
        for (int i = 0; i < count; i++) {
            threads[i] = new Thread(phils[i]);
            threads[i].start();
        }
        Thread.sleep(60000);
        for (MyPhil phil : phils) {
            phil.stopFlag = true;
        }
        for (Thread thread : threads) {
            thread.join();
        }
        for (MyPhil phil : phils) {
            System.out.println("Философ " + phil.pos + " поел " + phil.eatCount + " раз и прождал " + phil.waitTime);
        }
    }
 
    public void eat() {
        waitTime += System.currentTimeMillis() + startWait;
        System.out.println("Философ " + pos + " ест");
        try {
            Thread.sleep(rnd.nextInt(100));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        eatCount++;
        System.out.println("Философ " + pos + " поел");
    }
 
    public void think() {
        System.out.println("Философ " + pos + " думает");
        try {
            Thread.sleep(rnd.nextInt(100));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Философ " + pos + " проголодался");
        startWait = System.currentTimeMillis();
    }
}
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
12.10.2016, 21:29
Помогаю со студенческими работами здесь

Процессы, Обедающие философы
Здравствуйте! Нужна помощь с задачей о обедающих философах сделанная не на потоках как здесь...

Обедающие философы, Critical Section
Задача: Есть 5 философов. В столовой расположен круглый стол, вокруг которого расставлены 5 стульев. На столе находится одна большая...

Обедающие философы, перевод с Delphi
«Проблема обедающих философов» Программная реализация задачи на языке Delphi, нужно перевести в с# windows forms main.pas unit...

Обедающие философы. Решение методом монитора
Здравствуйте. Ищу решения проблемы обедающих философов методом монитора( он же официант, арбитр и т.д.) Есть у кого готовый код?


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Новые блоги и статьи
сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и источниками (напряжения, ЭДС и тока). Найти токи и напряжения во всех элементах. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru