0 / 0 / 0
Регистрация: 06.07.2013
Сообщений: 9
|
||||||||||||||||
1 | ||||||||||||||||
Спящий парикмахер. Многопоточность09.08.2013, 22:22. Показов 10205. Ответов 10
Метки нет (Все метки)
Доброго времени суток, уважаемые форумчане!
Прошу вашего совета. Начинаю осваивать Java и решил написать программку реализующую решение задачи спящего парикмахера. Формулировка задачи: Аналогия основана на гипотетической парикмахерской с одним парикмахером. У парикмахера есть одно рабочее место и приемная с несколькими стульями. Когда парикмахер заканчивает подстригать клиента, он отпускает клиента и затем идет в приёмную, чтобы посмотреть, есть ли там ожидающие клиенты. Если они есть, он приглашает одного из них и стрижет его. Если ждущих клиентов нет, он возвращается к своему креслу и спит в нем. Каждый приходящий клиент смотрит на то, что делает парикмахер. Если парикмахер спит, то клиент будит его и садится в кресло. Если парикмахер работает, то клиент идет в приёмную. Если в приёмной есть свободный стул, клиент садится и ждёт своей очереди. Если свободного стула нет, то клиент уходит. Основываясь на наивном анализе, вышеупомянутое описание по идее должно гарантировать, что парикмахерская функционирует правильно с парикмахером, стригущим любого пришедшего, пока есть клиенты, и затем спящим до появления следующего клиента. На практике же существует несколько конфликтных ситуаций, которые иллюстрируют общие проблемы планирования. Все эти конфликтные ситуации связаны с тем фактом, что действия и парикмахера, и клиента (проверка приёмной, вход в парикмахерскую, занятие места в приёмной, и т. д.) занимают неизвестное количество времени и/или могут происходить одновременно. Например, клиент может войти и заметить, что парикмахер работает, тогда он идет в приёмную. Пока он идет, парикмахер заканчивает стрижку, которую он делает и идет, чтобы проверить приемную, причём делает это быстрее направляющегося туда клиента. Так как в приёмной пока ещё никого нет (клиент ещё не дошел), он возвращается к своему месту и спит. Парикмахер теперь ждет клиента, а клиент ждет парикмахера. В другом примере два клиента могут прибыть в то же самое время, когда в приемной есть единственное свободное место. Они замечают, что парикмахер работает, идут в приёмную, и оба пытаются занять единственный стул. Начал писать код, пока только наброски: 3 класса: Посетитель
Решил использовать ReentrantLock (отсюда первый вопрос: есть ли вообще в этом смысл, не лучше ли сделать через Synchronized?) Имеется блокировка
Сделать публичный метод getBarberLock() и через него получить блокировку в классе посетитель и использовать там же при вызове метода проверки состояния парикмахера со стороны посетителя, но в тоже время понимаю, что это не совсем разумно делать публичные методы для работы с блокировками, однако других идей нет. Подскажите пожалуйста в каком направлении думать
0
|
09.08.2013, 22:22 | |
Ответы с готовыми решениями:
10
"Спящий парикмахер", используя семафоры "Спящий Парикмахер" спящий режим Спящий режим |
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
|
||||||
10.08.2013, 13:36 | 2 | |||||
Можно же синхронизироваться по креслу, клиент пришёл и смотрит кто там в кресле есть:
если парикмахер то сганяет его, если клиент - садиться на другое кресло (если оно есть - иначе на выход). Когда состояние кресла меняеться можно будить клиентов через notify. Вот отдалённый пример в тему synchronized и объекта синхронизирующегося по другому объекту (медведь ждёт горшок), это я какому-то студенту на экзамене писал поэтому чтобы ему было понятно всё в одном классе и ну очень много комментариев, думаю будет полезно для примера. Смысл задачи: пчёлы носят мёд в горшок (очень заботливые пчёлы - сразу в горшок), а медведь ест мёд когда горшок заполняется, до этого он спит, в этой модификации он ждёт пока пчёлы наносят все горшки с мёдом. Хотя я бы предпочёл изменить задачу чтобы пока поток медведь ждёт заполненный мёдом горшок пчёлы жалили его в мохнатую жопу, но увы и ах, задачи на экзамене составляю не я.
Надо кстати наверное разбить таки на пару файлов и запостить в свой блог этот код, сейчас почитал свой код и посмеялся с тогдашней задачи, думаю другие форумчане тоже оценят придуманную экзаменатором задачу
1
|
0 / 0 / 0
Регистрация: 06.07.2013
Сообщений: 9
|
|
10.08.2013, 14:43 [ТС] | 3 |
Спасибо большое за ответ и объяснения, сегодня попробую
Добавлено через 42 минуты Единственное, я не очень понял: Я себе представляю так, мы делаем синхронизированный метод, и если к этому методу обращаемся из двух потоков одновременно, то первый поток вызвавший метод захватывает блокировку и не дает работать с этим методом другому потоку, пока не закончит сам, так? То есть получается, мне необходимо сделать метод, например метод проверки состояния кресла и дергать его и со стороны посетителя и со стороны парикмахера?
0
|
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
|
|
11.08.2013, 11:04 | 4 |
Karlo_Dipetrio, не совсем или же ты не правильно выразился, ты синхронизируешься не по методу, а по обхекту (хотя в данном коде выглядит как-будто мы и правда ждём пока завершиться вызов метода). Видишь вон в моей задаче медведь синхронизируеться по списку горшков (изнчально по одному горшку) с мёдом.
Добавлено через 1 минуту Можешь кстати у Шилдта открыть раздел по многопоточности если видишь что тебе недостаёт знаний в этой теме, раздел книги всяко лучше статей в интернете и готовых примеров по которым сложнее разобраться если до этого не работал с многопоточностью.
1
|
0 / 0 / 0
Регистрация: 06.07.2013
Сообщений: 9
|
|
11.08.2013, 13:04 [ТС] | 5 |
Спасибо. Я по Хорстману читал, но видимо не уловил. Кажется теперь понял. Поправьте пожалуйста если я ошибаюсь: При выполнении синхронизированного метода, захватывается блокировка объекта с этим методом и любой другой поток не сможет выполнить ни один из синхронизированных методов заблокированного объекта пока первый поток не завершит работу с методом?
Добавлено через 13 минут Т.е., таким образом, если сделать в классе парикмахерской методы для проверки состояния кресла и для занятия кресла посетителем синхронизированными, то это обезопасит от ситуации, когда клиент может войти и заметить, что парикмахер работает, тогда он идет в приёмную. Пока он идет, парикмахер заканчивает стрижку, которую он делает и идет, чтобы проверить приемную, причём делает это быстрее направляющегося туда клиента. Так как в приёмной пока ещё никого нет (клиент ещё не дошел), он возвращается к своему месту и спит. Парикмахер теперь ждет клиента, а клиент ждет парикмахера?
0
|
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
|
|
12.08.2013, 01:31 | 6 |
Да
void synchronized method(){...} == void method() { synchronized(this) {...} } А вообще ты бы начал писать и решать задачу вот и посмотришь что получиться и как поступить
1
|
0 / 0 / 0
Регистрация: 06.07.2013
Сообщений: 9
|
|
12.08.2013, 01:34 [ТС] | 7 |
Да, спасибо, сегодня уже неплохо продвинулся! Огромное спасибо за советы
0
|
0 / 0 / 0
Регистрация: 06.07.2013
Сообщений: 9
|
|||||||||||||||||||||
15.08.2013, 23:30 [ТС] | 8 | ||||||||||||||||||||
Вобщем делал я делал, и что-то получилось) Не судите строго, но все же есть косяк, бывает ситуация, когда парикмахер заканчивает стрижку и должен сразу же проверить очередь клиентов, но один из клиентов может вклиниться в этот момент и проверить парикмахера и увидеть, что он занят, хотя тот закончил стрижку. Я так понимаю это происходит вне синхронизированного метода, то есть ошибка не в нем, или я не правильно понимаю. вот метод run() парикмахера:
Вот ошибочная ситуация: Посетитель 1 проверяет состояние парикмахера: парикмахер спит Посетитель 1 разбудил парикмахера и сел на стрижку Парикмахер стрижет посетителя: Посетитель 1 Парикмахер закончил стричь посетителя: Посетитель 1 Посетитель 2 проверяет состояние парикмахера: парикмахер занят работой Посетитель 2 занял место в приемной Парикмахер проверяет наличие клиентов: В очереди 1 из 3 Парикмахер стрижет посетителя: Посетитель 2 а вот полный код: Парикмахерская с парикмахером
0
|
0 / 0 / 0
Регистрация: 06.07.2013
Сообщений: 9
|
|
18.08.2013, 23:10 [ТС] | 9 |
Спасибо за ответы, Ваш пример с медведем очень здорово помог!) Gepar, Вроде все удалось) Переделал код
Тему можно закрыть
0
|
Модератор
12736 / 7566 / 1764
Регистрация: 25.07.2009
Сообщений: 13,954
|
||||||||||||||||||||||||||||||||||||
26.08.2013, 17:22 | 10 | |||||||||||||||||||||||||||||||||||
Задачка-то интересная, давно хотел сделать, да всё руки не доходили... Не совсем комильфо получилось - после закрытия ещё кто-то ждать усаживается, но в принципе интересно - приходят, стригутся...
1
|
0 / 0 / 0
Регистрация: 06.07.2013
Сообщений: 9
|
||||||||||||||||
26.08.2013, 17:44 [ТС] | 11 | |||||||||||||||
Спасибо за ответ! =)
У меня вот так получилось: Посетитель:
0
|
26.08.2013, 17:44 | |
26.08.2013, 17:44 | |
Помогаю со студенческими работами здесь
11
Спящий режим Спящий режим Спящий режим Спящий режим Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |