Чтение онлайн

на главную - закладки

Жанры

Философия Java3

Эккель Брюс

Шрифт:

public class DeadlockingDiningPhi1osophers {

public static void main(String[] args) throws Exception { int ponder = 5, if(args length > 0)

ponder = Integer.parselnt(args[0]); int size = 5; if(args length > 1)

size = Integer parselnt(args[l]); ExecutorService exec = Executors newCachedThreadPoolО; Chopstick[] sticks = new Chopstick[size]; for(int i = 0; i < size; i++)

sticksCi] = new ChopstickO; for(int 1=0. i < size, i++)

exec execute(new PhiTosopherC

sticks[i], sticks[(i+l) % size], i, ponder)); if(args length == 3 && args[2].equals("timeout")) TimeUnit.SECONDS sleep(5);

\ else {

System.out.рппШСНажмите 'Enter',

чтобы завершить работу"); System in readO;

}

exec shutdownNow;

}

} ///:-

Если философы почти не тратят время на размышления, они будут постоянно конкурировать за палочки при попытках поесть, и взаимные блокировки возникают гораздо чаще.

Первый аргумент командной строки изменяет значение ponder, влияющее на продолжительность размышлений. Если философов очень много или они проводят большую часть времени в размышлениях, взаимная блокировка может и не возникнуть, хотя ее теоретическая вероятность отлична от нуля. С нулевым аргументом взаимная блокировка наступает намного быстрее.

Объектам Chopstick не нужны внутренние идентификаторы; они идентифицируются по своей позиции в массиве sticks. Каждому конструктору Philosopher передаются ссылки на правую и левую палочки Chopstick. Последнему Philosopher в качестве правой палочки передается нулевой объект Chopstick; круг замыкается. Теперь может возникнуть ситуация, когда все философы одновременно попытаются есть, и каждый из них будет ожидать, пока сосед положит свою палочку. В программе наступает взаимная блокировка.

Если философы тратят на размышления больше времени, чем на еду, вероятность взаимной блокировки значительно снижается. Даже может возникнуть иллюзия, что программа свободна от блокировок (при ненулевом значении ponder или большом количестве объектов Philosopher), хотя на самом деле это не так. Именно этим и интересен настоящий пример: программа вроде бы ведет себя верно, тогда как на самом деле возможна взаимная блокировка.

Для решения проблемы необходимо осознавать, что тупик имеет место при стечении следующих четырех обстоятельств:

1. Взаимное исключение: по крайней мере один ресурс, используемый потоками, не должен быть совместно используемым. В нашем случае одной палочкой для еды не могут одновременно есть два философа.

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

3. Ресурс нельзя принудительно отбирать у задачи. Все процессы должны освобождать ресурсы естественным путем. Наши философы вежливы и не станут выхватывать палочки друг у друга.

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

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

каждый философ старается брать палочки в определенном порядке — сначала левую, потом правую. Из-за этого может возникнуть ситуация, когда каждый из них держит свою левую палочку и ждет освобождения правой, что и приводит к циклическому ожиданию. Если инициализировать последнего философа так, чтобы он сначала пытался взять левую палочку, а потом правую, взаимная блокировка станет невозможна. Это всего лишь одно решение проблемы, но вы можете предотвратить ее, нарушив одно из оставшихся условий (за подробностями обращайтесь к специализированной литературе по многозадачному программированию):

//. concurrency/FixedDiningPhilosophers.java

// Обедающие философы без взаимной блокировки.

// {Args: 5 5 timeout}

import java.util.concurrent.*;

public class FixedDiningPhilosophers {

public static void main(String[] args) throws Exception {

int ponder = 5; if (args.length > 0)

ponder = Integer.parselnt(args[0]), int size = 5, if(args.length > 1)

size = Integer parselnt(args[l]); ExecutorService exec = Executors.newCachedThreadPool; Chopstick[] sticks = new Chopstick[size]. for(int i = 0, i < size; i++)

sticks[i] = new ChopstickO; for(int i = 0: i < size; i++) if(i < (size-1))

exec execute(new Philosopher(

sticks[i], sticks[i+l], i, ponder));

else

exec.execute(new Philosopher(

sticksEO], sticksEi], i, ponder)), if(args.length == 3 && argsE2].equals("timeout")) TimeUnit SECONDS.sleep(5);

else {

System out printlnC'Press 'Enter' to quit"); System, in. readO.

}

exec shutdownNow.

}

} ///:-

Проследив за тем, чтобы последний философ брал и откладывал левую палочку раньше правой, мы устраняем взаимную блокировку.

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

Новые библиотечные компоненты

В библиотеке java.utiLconcurrent из Java SE5 появился целый ряд новых классов, предназначенных для решения проблем многозадачности. Научившись пользоваться ими, вы сможете создавать более простые и надежные многозадачные программы.

В этом разделе приведено немало примеров использования различных компонентов. Другие, относительно редко встречающиеся компоненты, здесь не рассматриваются.

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

CountDownLatch

Класс синхронизирует задачи, заставляя их ожидать завершения группы операций, выполняемых другими задачами.

Объекту CountDownLatch присваивается начальное значение счетчика, а все задачи, вызвавшие await для этого объекта, блокируются до момента обнуления счетчика. Другие задачи могут уменьшать счетчик, вызывая метод countDown для объекта (обычно это делается тогда, когда задача завершает свою работу). Класс CountDownLatch рассчитан на «одноразовое» применение; счетчик не может возвращаться к прежнему состоянию. Если вам нужна версия с возможностью сброса счетчика, воспользуйтесь классом CyclicBarrier.

Поделиться:
Популярные книги

Архил...? 4

Кожевников Павел
4. Архил...?
Фантастика:
фэнтези
попаданцы
альтернативная история
5.50
рейтинг книги
Архил...? 4

Мятежник

Прокофьев Роман Юрьевич
4. Стеллар
Фантастика:
боевая фантастика
7.39
рейтинг книги
Мятежник

Дурашка в столичной академии

Свободина Виктория
Фантастика:
фэнтези
7.80
рейтинг книги
Дурашка в столичной академии

Котенок. Книга 3

Федин Андрей Анатольевич
3. Котенок
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Котенок. Книга 3

Аристократ из прошлого тысячелетия

Еслер Андрей
3. Соприкосновение миров
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Аристократ из прошлого тысячелетия

Печать мастера

Лисина Александра
6. Гибрид
Фантастика:
попаданцы
технофэнтези
аниме
фэнтези
6.00
рейтинг книги
Печать мастера

Господин следователь. Книга 3

Шалашов Евгений Васильевич
3. Господин следователь
Детективы:
исторические детективы
5.00
рейтинг книги
Господин следователь. Книга 3

Вернуть невесту. Ловушка для попаданки 2

Ардова Алиса
2. Вернуть невесту
Любовные романы:
любовно-фантастические романы
7.88
рейтинг книги
Вернуть невесту. Ловушка для попаданки 2

Командир Красной Армии

Поселягин Владимир Геннадьевич
1. Командир Красной Армии
Фантастика:
попаданцы
8.72
рейтинг книги
Командир Красной Армии

Рота Его Величества

Дроздов Анатолий Федорович
Новые герои
Фантастика:
боевая фантастика
8.55
рейтинг книги
Рота Его Величества

Босс Мэн

Киланд Ви
Любовные романы:
современные любовные романы
8.97
рейтинг книги
Босс Мэн

Два лика Ирэн

Ром Полина
Любовные романы:
любовно-фантастические романы
6.08
рейтинг книги
Два лика Ирэн

Не грози Дубровскому! Том III

Панарин Антон
3. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Не грози Дубровскому! Том III

Идеальный мир для Лекаря 27

Сапфир Олег
27. Лекарь
Фантастика:
аниме
фэнтези
5.00
рейтинг книги
Идеальный мир для Лекаря 27