Java: Является ли ServerSocket.accept потокобезопасным? - PullRequest
12 голосов
/ 22 мая 2009

Для школьного проекта мы создаем многопоточный сервер на Java 5.0. Этот проект сосредоточен на аспекте параллельности сервера.

У нас есть несколько тем, посвященных обработке запросов. Для этого им необходимо вызвать ServerSocket.accept () для принятия новых соединений. Наш выбор состоял в том, чтобы запустить их несколько и позволить им обрабатывать входящие соединения, предполагая, что два потока не могут одновременно принимать () одно и то же соединение.

Но теперь главная проблема в том, что мы не можем найти в API ничего, что гарантировало бы нам такое поведение (или мы не выглядели правильно), и у нас нет ничего, кроме доказательства «все работает».

Есть ли у кого-нибудь источник для поиска такого рода информации о методах Java?

Ответы [ 2 ]

25 голосов
/ 22 мая 2009

Краткий ответ : если в документации не указано, что что-то является потокобезопасным, вы должны предположить, что это не так. Вам необходимо самостоятельно согласовать потоки, чтобы убедиться, что никакие два потока не используют сокет сервера одновременно.

Это особенно важно, потому что какой-то другой код мог зарегистрировать свою собственную реализацию сокета с ServerSocket.setSocketFactory. Даже если реализация сокета по умолчанию является поточно-ориентированной, пользовательские реализации не обязательно должны быть. В документации ничего не говорится об этом.

Длинный ответ: стандартная реализация Windows

Вы можете скачать и проверить исходный код java SE 1.6 .

Я начал с \j2se\src\share\classes\java\net\ServerSocket.java, и оттуда след привел к PlainSocketImpl.java. Метод PlainSocketImpl.Accept помечен как native.

Собственный код C ++ для Windows находится в \j2se\src\windows\native\java\net\PlainSocketImpl.c. Используется функция winsock accept . Из статьи MSDN о WinSock (выделено мое):

Под Windows NT и Windows 2000, Поддержка Windows Sockets для 16-битных Приложения основаны на WINSOCK.DLL. Для 32-битных приложений, поддержка находится в WSOCK32.DLL. API предоставлены идентичны за исключением того, что 32-разрядный версии имеют параметры, расширенные до 32 биты. Под Win32 потокобезопасность в комплект поставки.

Так что, по крайней мере в Windows, Socket.Accept является поточно-ориентированным в том смысле, что не позволяет двум потокам принимать одно и то же соединение. В реализации ServerSocket также имеется инфраструктура (например, метод Close () использует блокировку), которая указывает, что она предназначена для обеспечения безопасности потоков.

9 голосов
/ 22 мая 2009

Это не совсем отвечает на ваш вопрос, но выполнение accept () в нескольких потоках звучит так, как будто что-то не так с дизайном сервера.

Обычно не нужно запускать accept () из нескольких потоков.

Ваш код должен выглядеть примерно так:

while (serverIsUpAndRunning())
{
    // Wait for an incoming connection.
    Socket s = serverSocket.accept();
    // Spawn a thread to handle the socket,
    // so that we don't block new connections.
    SocketHandlerThread t = new SocketHandlerThread(s);
    t.start();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...