Предложения

  • 5
  • Недоступна
Не используя synchronized сделай так, чтобы количество сделанных и принятых предложений было одинаковым.
Вы не можете решать эту задачу, т.к. не залогинены.
Комментарии (111)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
WillMage
Уровень 28, Новосибирск
5 мая, 11:45
Очень красивая задачка, в неё надо добавить пункт в условие: 1. Разберитесь что делает программа.
Anonymous #3036451
Уровень 22, Falls Church, United States
30 апреля, 11:33
Если преобразовать код аля компилятор, то без volatile будет примерно так:
public static class MakeProposal extends Thread {
    @Override
    public void run() {
        int proposal = Solution.proposal; //помещаем в кэш
        int thisProposal = proposal;

        while (proposal < 10) {
            System.out.println("Сделано предложение №" + (thisProposal + 1));
            proposal = ++thisProposal;
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Solution.proposal = proposal; //возвращаем из кэша в медленную память
    }
}
MakeProposal инкрементирует переменную proposal до 10 и возвращает ее в медленную память. AcceptProposal:
public static class AcceptProposal extends Thread {
    @Override
    public void run() {
        int proposal = Solution.proposal; //помещаем в кэш 0, или,
       //если нить MakeProposal успела сделать несколько тактов, то больше
        int thisProposal = proposal;

        while (thisProposal < 10) {
            if (thisProposal != proposal) {
                System.out.println("Принято предложение №" + proposal);
                thisProposal = proposal;
            }
        }
        //сюда программа не дойдет
        Solution.proposal = proposal; //возвращаем из кэша в медленную память
    }
}
Тут наблюдаем бесконечный цикл, т. к. proposal и thisProposal всегда равны друг другу
Михаил Кладовщик с кучей времени
10 декабря 2021, 12:00
Интересное наблюдение. В том виде, в каком задача подана сначала, IDE сразу же ставит предупреждение на строчку
if (thisProposal != proposal) {
"Условие всегда неверно" Чтобы убедиться в этом поставил
System.out.println(proposal);
сразу после проверки условия, и действительно, оно ни разу не сработало. То есть поток accept по умолчанию не видит изменения переменной proposal. Но потом интереса ради поставил этот же самый
System.out.println(proposal);
буквально на строку выше, перед проверкой условия. И о чудо. IDE убрала свое предупреждения. И программа отработала как надо (10 сделано 10 принято по порядку). Сначала я подумал, что из-за того что мы пользуемся переменной proposal в этом месте то jvm перестает хотеть делать ее локальную версию и работает с общей памятью, но потом снова ради интереса я изменил сроку на просто
System.out.print("");
и снова же, все отлично работает. То есть строка, которая по моим скудным знаниям вообще никак не должна влиять на программу, заставляет jvm изменить способ работы с переменной - способом аналогичным добавлением volatile. И что интересно IDE это видит и убирает предупреждение.
Сергей Коваленко
Уровень 37, Краснодар
4 января, 19:41
ха, и правда! интересно почему - может рефлексия? 🙄
Dmitry B
Уровень 20, DownTown
3 декабря 2021, 09:48
Мои предположения, в какой момент переменная proposal попадает в кэш. 1. Первый проход. Переменная proposal = 0 1.1. Запускается нить Accept, не происходит ничего, переменная не меняется. В методе run нити Accept сохраняется локальная переменная thisProposal = 0; 1.2. Запускается нить Make, выводится на экран "Сделано предложение №1 [т.к. 0 (текущее значение переменной proposal) + 1]". Значение переменной proposal инкрементируется. Нить засыпает. 2. Второй проход. Proposal = 1. 2.1. Пока нить Make спит, нить Accept успевает запуститься и выдать "Принято предложение №1" т.к. текущее значение переменной proposal уже 1, и по условию сравнения локальной переменной метода thisProposal с proposal, мы выдаём на экран вышеупомянутую фразу. Значение локальной переменной thisProposal становится = 1. 2.2. Нить Make просыпается, начинает работать с переменной proposal, инкрементирует её, переменная proposal (уже = 2) помещается в кэш (наверное по критерию кол-во обращений к переменной за некий короткий промежуток времени). "Медленная" память продолжает содержать значение proposal = 1. Нить Make засыпает. 2.3. Нить Accept, работая со значением proposal = 1, сравнивая её со значением локальной переменной своего метода thisProposal = 1, делает ничего. 2.4. Нить Make отрабатывает все значения proposal до 10. 2.5. Нить Accept продолжает молотить вхолостую, поэтому программа не завершается. Так?
Sergey Kornilov
Уровень 38, Petropavlovsk, Казахстан
3 ноября 2021, 16:52
Всего эту задачу решили 27311 учеников.
Anna Avilova architect
18 марта, 14:05
где вы видете эти данные? 🤨
Sergey Kornilov
Уровень 38, Petropavlovsk, Казахстан
19 марта, 15:06
Intellij IDEA + плагин от javarush (поиск в интернете)
Anna Avilova architect
21 марта, 06:57
спасибо! идея с плагином у меня установлена, гляну при случае )
Igor Stupnik
Уровень 30
13 июля 2021, 11:55
интересно, а кто-нибудь сделал synchronized proposal, до volatile такой же результат?
George
Уровень 33, Москва, Россия
15 сентября 2021, 06:51
валидатор говорит, что бесконечный цикл
Вадим
Уровень 23, Москва
18 июня 2021, 21:49
Здесь еще немаловажную роль играет слип в первом методе. Думаю если его убрать равномерности не получится даже с волатайле. Со слипом 1й метод играет как бы в поддавки со вторым - позволяет второму гарантированно себя догнать.
Yuri_S Инженер-конструктор 2к.
8 января, 14:26
Угу, поставил слип 10мс - остались непринятые предложения.
Вадим
Уровень 23, Москва
18 июня 2021, 21:43
Хочется сказать : Люди, спасибо, что Вы есть! С Вами учиться гораздо интереснее (чем с Амиго)))
Дмитрий
Уровень 36, Москва
25 марта 2021, 19:01
а теперь вопрос, как это сделать с помощью synchronized?
2 февраля 2021, 11:37
Убрал if в AcceptProposal, "синхронизовал" его через Thread.sleep() с MakeProposal, сначала предложение делается, потом принимается через равные промежутки времени. Решение ужасное, но рабочее)) Лишь на этапе валидации с комментарием про volatile понял, как она должна работать..