对于学校的一个项目,我们正在用 Java 5.0 制作一个多线程服务器。该项目以服务器的并发方面为中心。
我们有一些线程专门用于处理请求。为此,他们调用 ServerSocket.accept() 来接受新连接。我们的选择是启动一堆它们,让它们以两个线程不能同时接受()同一个连接的假设来处理传入的连接。
但现在主要的问题是我们在 API 中找不到任何东西来保证我们的这种行为(或者我们看起来不正确),除了“它有效”的证明之外,我们什么也没有。
有没有人在java方法上寻找这种信息的来源?
对于学校的一个项目,我们正在用 Java 5.0 制作一个多线程服务器。该项目以服务器的并发方面为中心。
我们有一些线程专门用于处理请求。为此,他们调用 ServerSocket.accept() 来接受新连接。我们的选择是启动一堆它们,让它们以两个线程不能同时接受()同一个连接的假设来处理传入的连接。
但现在主要的问题是我们在 API 中找不到任何东西来保证我们的这种行为(或者我们看起来不正确),除了“它有效”的证明之外,我们什么也没有。
有没有人在java方法上寻找这种信息的来源?
简短的回答:如果文档没有指定某些东西是线程安全的,那么您必须假设它不是。您需要自己进行线程之间的协调,以确保没有两个线程同时使用服务器套接字。
这一点尤其重要,因为其他一些代码可能已经使用ServerSocket.setSocketFactory
. 即使默认套接字实现是线程安全的,自定义实现也不必如此。文档中没有任何内容这么说。
长答案:默认 Windows 实现
您可以下载并检查java SE 1.6 源代码。
我从那里开始,\j2se\src\share\classes\java\net\ServerSocket.java
从那里开始通往PlainSocketImpl.java
. 该PlainSocketImpl.Accept
方法标记为native
。
Windows 的本机 C++ 代码位于\j2se\src\windows\native\java\net\PlainSocketImpl.c
. 它使用winsock 接受函数。来自关于 WinSock 的 MSDN 文章(重点是我的):
在 Windows NT 和 Windows 2000 下,对 16 位应用程序的 Windows 套接字支持基于 WINSOCK.DLL。对于 32 位应用程序,支持在 WSOCK32.DLL 中。提供的 API 是相同的,只是 32 位版本的参数扩展为 32 位。在 Win32 下,提供了线程安全。
所以至少在 Windows 上,Socket.Accept
是线程安全的,因为它不会让两个线程接受相同的连接。实现中还有基础设施ServerSocket
(例如 Close() 方法使用锁),这表明它是线程安全的。
这并不能完全回答您的问题,但是在多个线程上运行 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();
}