2009-05-22 7 views
11

Pour un projet à l'école, nous faisons un serveur multithread en Java 5.0. Ce projet est centré sur l'aspect de la concurrence d'un serveur.Java: threadsocket.accept threadsafe?

Nous avons des threads dédiés au traitement des requêtes. Pour ce faire, ils ont un appel à ServerSocket.accept() pour accepter les nouvelles connexions. Notre choix était de commencer un tas d'entre eux et de les laisser traiter les connexions entrantes avec l'hypothèse que deux threads ne peuvent pas accepter() la même connexion en même temps. Mais maintenant le principal problème est que nous ne trouvons rien dans l'API qui nous garantisse ce comportement (ou que nous n'avons pas l'air correct) et nous n'avons rien d'autre que la preuve "ça marche".

Est-ce que quelqu'un a une source pour rechercher ce genre d'information sur les méthodes java?

+0

Nous savons que cette conception n'est pas vraiment bonne et nous l'avons déjà modifiée pour utiliser un pool de threads de travail. Maintenant nous avons seulement un thread qui accepte et envoie les demandes aux threads de travail. Je serais toujours savoir s'il existe des informations quelque part sur la thread-sécurité des méthodes Java. –

Répondre

25

Réponse courte: si la documentation ne précise pas que quelque chose est thread-safe, vous devez supposer que ce n'est pas. Vous devez effectuer vous-même la coordination entre les threads pour vous assurer que deux threads n'utilisent pas la socket serveur en même temps.

Ceci est particulièrement important car un autre code pourrait avoir enregistré sa propre implémentation de socket avec ServerSocket.setSocketFactory. Même si l'implémentation de socket par défaut est thread-safe, les implémentations personnalisées ne doivent pas l'être. Il n'y a rien dans la documentation qui le dit.

Réponse longue: la mise en œuvre par défaut de Windows

Vous pouvez télécharger et inspecter le java SE 1.6 source code.

J'ai commencé à \j2se\src\share\classes\java\net\ServerSocket.java et à partir de là, la piste a conduit à PlainSocketImpl.java. La méthode PlainSocketImpl.Accept est marquée native. Le code C++ natif de Windows est \j2se\src\windows\native\java\net\PlainSocketImpl.c. Il utilise la fonction winsock accept. D'un MSDN article on WinSock (Souligné par l'auteur):

Sous Windows NT et Windows 2000, support Windows Sockets 16 bits applications est basée sur WINSOCK.DLL. Pour les applications 32 bits, le support se trouve dans WSOCK32.DLL. Les API fournies sont identiques, sauf que les versions 32 bits ont des paramètres élargis à 32 bits. Sous Win32, la sécurité du fil est fournie.

Ainsi, au moins sur les fenêtres, Socket.Accept est thread-safe dans le sens où il ne laissera pas deux fils acceptent la même connexion. Il existe également une infrastructure dans l'implémentation ServerSocket (e.g. la méthode Close() utilise un verrou) qui indique qu'il est destiné à être thread-safe.

+2

+1 pour la réponse détaillée et bien documentée – talonx

+0

nouveau +1 pour cette excellente réponse – Kartoch

8

Cela ne répond pas tout à fait à votre question, mais l'exécution de accept() sur plusieurs threads sonne comme si quelque chose n'allait pas dans la conception du serveur.

Habituellement, il ne devrait pas être nécessaire d'exécuter accept() à partir de plusieurs threads.

Votre code devrait ressemble à quelque chose comme ceci:

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

Chaque thread de travail acceptant sa propre connexion est un concept parfaitement valide. Il profite de ne pas avoir à passer à d'autres threads. –

+1

Vous pensez à un pool de threads fixe où chaque thread est en concurrence pour l'accept()? C'est certainement un inversement de la propriété habituelle des threads. Je dois admettre que je ne peux pas voir comment "le coût de la remise" à un nouveau thread (ou un à partir d'un pool de threads) justifierait la complexité dans la plupart des cas. Existe-t-il des exemples où ce type de conception est pratique? – Nuoji

+3

Plus important encore, Java ne garantit * PAS * la sécurité des threads d'accepter - Le fait que l'API native sous-jacente dans Windows (comme cité par la réponse acceptée), n'a aucun sens. –