Обеденные философы: подход Чанди-Мисры: как избежать тупика?

Я пробую это, однако вопрос: в wiki третий пункт этого алгоритма говорит:

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

Я пытаюсь понять, почему это не приводит к тупику? если у одного философа есть одна чистая вилка, и он ждет, чтобы получить другую чистую вилку от соседнего закусочного/философа, который, в свою очередь, тоже ждет вилку, это может привести к тупиковой ситуации, верно? один философ всегда ждет вилки от другого?

ps: я новичок в потоках и параллелизме, воспринял это как учебный проект.

Изменить: фактическое место, где даются вилки, публикуя это, чтобы спросить, должны ли вилки быть изменчивыми или нет. pLeft, pRight — левые и правые философы, fLeft и fRight — левая и правая вилки.

private Fork giveFork(Philosopher diner) {
        Fork forkToGive;

        if (this.pLeft.equals(diner)) {
            // give left fork to left philosopher
            if (this.fLeft.isClean)
                forkToGive = null; // don't give
            else {
                forkToGive = new Fork(this.fLeft.id, true); // give the fork
            }

        } else if (diner.pRight.equals(this)) {
            // give right fork to right philosopher
            if (this.fRight.isClean)
                forkToGive = null;
            else {
                forkToGive = new Fork(this.fRight.id, true);
            }
        } else {
            // default value , i'm not yet sure if this code
            // can be theoretically reached
            forkToGive = null;
        }

        return forkToGive;

    }

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


person Somjit    schedule 11.10.2013    source источник
comment
В описании сказано, что философ отдает вилку, если она грязная, а изначально все вилки грязные.   -  person Victor Sorokin    schedule 11.10.2013
comment
Верно, но я не понимаю, как инициализировать все вилки? Держу ли я коллекцию вилок? и менять их на чистые/грязные со временем? Я пытаюсь иметь как можно больше неизменяемости, поэтому я решил не хранить коллекцию изменяемых вилок, а создавать и давать новые чистые вилки, когда это необходимо.   -  person Somjit    schedule 11.10.2013
comment
вилки являются общим ресурсом и должны быть изменяемыми (в противном случае весь протокол не нужен, так как каждый философ всегда может получить чистую пару вилок). Как правило, все причудливые протоколы синхронизации необходимы для управления изменяемыми данными, общими для процессов/потоков, если ваши данные неизменяемы (чисто функциональные), вам не нужно беспокоиться о синхронизации.   -  person Victor Sorokin    schedule 11.10.2013
comment
С точки зрения философа, который дает грязную вилку, он должен сначала ее очистить, теперь скажем, я создаю копию грязной вилки, только делая ее чистой, и заменяю грязную на новую чистую, есть еще одна вилка, и неизменяемость тоже..   -  person Somjit    schedule 11.10.2013
comment
Нет необходимости ничего синхронизировать, если вы можете создавать новые экземпляры ресурсов. Только когда ресурсы ограничены (например, файловое пространство на диске, сетевые подключения или память), возникает необходимость в синхронизации (сотрудничестве) акторов.   -  person Victor Sorokin    schedule 11.10.2013
comment
Я отредактировал свой пост, добавив немного кода, и почему я чувствую, что синхронизация все еще необходима. Если бы вы могли взглянуть, было бы здорово.   -  person Somjit    schedule 11.10.2013
comment
Предполагая, что giveFork() выполняется философом, который предоставляет форк, вам потребуется синхронизация, чтобы вернуть сгенерированный форк запрашивающей стороне (например, через wait()/notifyAll()). Но этот код более сложен, чем необходимо из-за создания форка. На самом деле, нет необходимости иметь выделенный класс Fork, все, что вам нужно, это массив ForkState forks[philosophersNr], и ваши стороны синхронизируются на нем.   -  person Victor Sorokin    schedule 11.10.2013


Ответы (1)


Источник, который вы цитируете, объясняет это:

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

Итак, вам нужно инициализировать систему до асимметричного состояния, а набор правил рассчитан на то, чтобы не выходить из желаемого (нетупикового состояния).

person jev    schedule 11.10.2013
comment
Эй, спасибо за упоминание этой части. Я скучаю по этому . Но я действительно не понимаю, как сохранить свои вилки: изменяемые или нет. вы можете помочь ? - person Somjit; 11.10.2013
comment
оба должны работать, поскольку в любой точке разветвления есть только один владелец: исходный алгоритм разработан для распределенной среды, поэтому он помогает мыслить с точки зрения передачи сообщений (поэтому каждый раз, когда вы проходите разветвление, вы создаете и отправляете новое сообщение). ) - person jev; 11.10.2013