Реализация алгоритма Java - Dekkers приводит к двум потокам в критической секции

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

Ниже приведен код моей реализации для первого железнодорожного пути.

while (allowed) {
        choochoo();
        setWantToUseTrack(0,true);
        while (getWantToUseTrack(1)) {
            if (getTurn() != 0) {
                setWantToUseTrack(0,false);
                while (getTurn() != 0) {
                    //wait loop
                }
                setWantToUseTrack(0, true);
            }
        }
        //critical section starts
        crossPass();
        //critical section ends
        setTurn(1);
        setWantToUseTrack(0,false);
    }
}

Ниже приведен код моей реализации второго железнодорожного пути.

while (allowed) {
        choochoo();
        setWantToUseTrack(1,true);
        while (getWantToUseTrack(0)) {
            if (getTurn() != 1) {
                setWantToUseTrack(1,false);
                while (getTurn() != 1) {
                    //wait loop
                }
                setWantToUseTrack(1,true);
            }
        }
        //critical section starts
        crossPass();
        //critical section ends
        setTurn(0);
        setWantToUseTrack(1,false);
    }

Когда этот код запускается, иногда оба поезда попадают в критическую секцию одновременно. Я не вижу логической ошибки. Я что-то упустил из своей реализации?

1 ответ

Возможно, что произойдет следующее (только один пример):

  1. Во втором треке setWantToUseTrack(1,false); вызывается.
  2. В первом треке предикат проверяется: while (getWantToUseTrack(1)), чтобы второй поток не останавливался в while петля.

    Это абсолютно осуществимо, поскольку первый трек может быть остановлен choochoo(); до (1.) и второй дорожки до (2.).

  3. метод getWantToUseTrack возвращается false для 0 и 1.

Создание цикла для перехвата потока до тех пор, пока не освободится критическая секция, немного опасно. Вы можете сделать раздел потокобезопасным, используя synchronized с crossPass определение.

Другие вопросы по тегам