Servlet doGet синхронизации - не работает? - PullRequest
4 голосов
/ 22 мая 2011

Я знаю, что это простой вопрос, но я как-то запутался.

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

Учтите, что у нас есть следующий код в MyServlet (я исключил обработку исключений и тому подобное):

synchronized protected void doGet( ... ...){
    PrintWritet pw=response.getWriter();
    String param=request.getParameter("p");

    if(param.equals("a")){
        wait();
    }else{
        notifyAll();
    }

    pw.write("Hello!");
}

Я ожидаю, что этот сервлет застрянет, потому что первый поток (с param = a), который входит в этот метод, будет ждать вечно, потому что любой другой будущий поток застрянет перед doGet из-за синхронизированного ключевого слова, и из-за этого notifyAll никогда не будет выполнено.

Теперь, если я открою новую вкладку в браузере и нажму / MyServlet? P = a, браузер ожидает 127.0.0.1 ... После этого я открываю новую вкладку и нажимаю / MyServlet? P = b (или что-нибудь, что есть! = A), первая вкладка освобождается и распечатывает «Привет!» сообщение.

Это означает, что второй поток вошел в doGet и выполнил notifyAll.

Почему это происходит? Что я пропустил?

1 Ответ

8 голосов
/ 22 мая 2011

Поскольку wait() снимает блокировку, ранее полученную путем ввода блока synchronized.Из javadoc для Object.wait:

Поток освобождает владельца этого монитора и ожидает, пока другой поток не уведомит потоки, ожидающие на мониторе этого объекта, чтобы он проснулся либо посредством вызова метода notify, либо notifyAll.метод.Затем поток ожидает, пока он не сможет вновь получить право собственности на монитор, и возобновит выполнение.

Таким образом, ваш первый запрос получает блокировку, входит в метод doGet и вызывает wait (который освобождаетзамок и ждет).Второй запрос получает блокировку, вводит doGet и вызывает notifyAll, что пробуждает поток первого запроса.

Это критический , что вы внимательно прочитали документацию для таких методов, как wait и notify / notifyAll до того, как вы их используете, иначе у вас возникнут проблемы.

...