2009-05-22 9 views
11

Für ein Projekt in der Schule machen wir einen Multithread-Server in Java 5.0. Dieses Projekt konzentriert sich auf den Übereinstimmungsaspekt eines Servers.Java: Ist ServerSocket.accept threadsafe?

Wir haben einige Threads für die Bearbeitung der Anfragen. Dazu müssen sie einen ServerSocket.accept() aufrufen, um neue Verbindungen zu akzeptieren. Unsere Wahl war, eine Reihe von ihnen zu starten und sie die eingehenden Verbindungen mit der Annahme behandeln zu lassen, dass zwei Threads die gleiche Verbindung nicht gleichzeitig akzeptieren() können.

Aber jetzt ist das Hauptproblem, dass wir nichts in der API finden können, die uns dieses Verhalten garantieren (oder wir sahen nicht richtig aus) und wir haben nichts außer dem "es funktioniert" Beweis.

Hat jemand eine Quelle, um nach dieser Art von Informationen über die Java-Methoden zu suchen?

+0

Wir wissen, dass dieses Design nicht wirklich gut ist und wir haben es bereits geändert, um einen Pool von Worker Threads zu verwenden. Jetzt haben wir nur einen Thread, der die Anfragen akzeptiert und an die Worker-Threads sendet. Ich würde immer noch wissen, ob es irgendwo Informationen über die Thread-Sicherheit von Java-Methoden gibt. –

Antwort

25

Kurze Antwort: Wenn die Dokumentation nicht an, dass etwas Thread-sicher ist, dann müssen Sie davon ausgehen, dass es nicht ist. Sie müssen die Koordination zwischen den Threads selbst durchführen, um sicherzustellen, dass keine zwei Threads den Server-Socket gleichzeitig verwenden.

Dies ist besonders wichtig, weil ein anderer Code eine eigene Socket-Implementierung mit ServerSocket.setSocketFactory registriert haben könnte. Auch wenn die Standard-Socket-Implementierung Thread-sicher ist, müssen benutzerdefinierte Implementierungen nicht erforderlich sein. In der Dokumentation steht nichts darüber.

Lange Antwort: die Standard-Windows-Implementierung

Sie können die java SE 1.6 source code herunterladen und inspizieren.

Ich begann um \j2se\src\share\classes\java\net\ServerSocket.java und von dort führte der Weg zu PlainSocketImpl.java. Die PlainSocketImpl.Accept Methode ist als native markiert.

Der native C++ - Code für Windows ist in \j2se\src\windows\native\java\net\PlainSocketImpl.c. Es verwendet die winsock accept Funktion. Von einer MSDN article on WinSock (Hervorhebung von mir):

unter Windows NT und Windows 2000, Windows Sockets Unterstützung für 16-Bit-Anwendungen basiert auf WINSOCK.DLL. Für 32-Bit-Anwendungen ist die Unterstützung in WSOCK32.DLL. Die bereitgestellten APIs sind identisch, mit der Ausnahme, dass die 32-Bit-Versionen Parameter auf 32 Bits erweitert haben. Unter Win32 wird Thread-Sicherheit geliefert.

So zumindest an Fenstern, ist Socket.Accept Faden sicher in dem Sinne, dass es nicht zwei Threads übernehmen die gleiche Verbindung lassen wird. Es gibt auch eine Infrastruktur in der ServerSocket Implementierung (e.G. Die Methode Close() verwendet eine Sperre), die angibt, dass sie Thread-sicher sein soll.

+2

+1 für die detaillierte, gut recherchierte Antwort – talonx

+0

wieder +1 für diese großartige Antwort – Kartoch

8

Das beantwortet Ihre Frage nicht ganz, aber das Ausführen von accept() bei mehreren Threads klingt, als ob etwas mit dem Design des Servers nicht stimmt.

Normalerweise sollte es nicht nötig sein, accept() von mehreren Threads auszuführen.

Der Code sollte in etwa so aussieht:

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(); 
} 
+0

Jeder Worker-Thread, der seine eigene Verbindung akzeptiert, ist ein perfekt gültiges Design. Es profitiert davon, nicht zu anderen Threads übergeben zu müssen. –

+1

Sie denken an einen festen threadpool, wo jeder Thread um die accept() konkurriert? Das ist sicherlich eine Umkehrung des üblichen Threadbesitzes. Ich muss zugeben, dass ich nicht sehen kann, wie "die Kosten der Übergabe" an einen neuen Thread (oder einen Thread aus einem Threadpool) die Komplexität in den meisten Fällen rechtfertigen würden. Gibt es Beispiele, wo diese Art von Design praktisch ist? – Nuoji

+3

Noch wichtiger ist, dass Java * NOT * garantiert die Threadsicherheit von accept - Die Tatsache, dass die zugrunde liegende native API in Windows (wie von der angenommenen Antwort zitiert) ist, ist bedeutungslos. –

Verwandte Themen