2009-05-22 50 views
11

Per un progetto a scuola, stiamo creando un server multithread in Java 5.0. Questo progetto è centrato sull'aspetto concurrence di un server.Java: ServerSocket.accept è threadsafe?

Abbiamo alcuni thread dedicati al trattamento delle richieste. Per fare ciò, hanno una chiamata a ServerSocket.accept() per accettare nuove connessioni. La nostra scelta era di iniziare un sacco di loro e lasciare che trattassero le connessioni in entrata con l'ipotesi che due thread non possano accettare() la stessa connessione allo stesso tempo.

Ma ora il problema principale è che non siamo in grado di trovare nulla nell'API che ci garantisca questo comportamento (o non abbiamo avuto un aspetto corretto) e non abbiamo nient'altro che la prova "funziona".

Qualcuno ha una fonte per cercare questo tipo di informazioni sui metodi Java?

+0

Sappiamo che questo design non è molto buono e lo abbiamo già modificato per utilizzare un pool di thread di lavoro. Ora abbiamo solo un thread che accetta e invia le richieste ai thread worker. Vorrei ancora sapere se ci sono informazioni da qualche parte sulla sicurezza dei thread dei metodi java. –

risposta

25

Risposta breve: se la documentazione non specifica che qualcosa è thread-safe, allora si deve presumere che non lo è. È necessario eseguire personalmente il coordinamento tra i thread per assicurarsi che non ci siano due thread che utilizzano contemporaneamente il socket del server.

Ciò è particolarmente importante perché un altro codice potrebbe aver registrato la propria implementazione socket con ServerSocket.setSocketFactory. Anche se l'implementazione socket predefinita è thread-safe, non è necessario che le implementazioni personalizzate siano. Non c'è nulla nella documentazione che lo dice.

Risposta lunga: il default di Windows Attuazione

È possibile scaricare e controllare la java SE 1.6 source code.

Ho iniziato a \j2se\src\share\classes\java\net\ServerSocket.java e da lì il sentiero ha portato a PlainSocketImpl.java. Il metodo PlainSocketImpl.Accept è contrassegnato come native.

Il codice C++ nativo per Windows è \j2se\src\windows\native\java\net\PlainSocketImpl.c. Usa la funzione winsock accept. Da un MSDN article on WinSock (sottolineatura mia):

In Windows NT e Windows 2000, Windows Sockets il supporto per 16 bit applicazioni si basa su WINSOCK.DLL. Per le applicazioni a 32 bit, il supporto è in WSOCK32.DLL. Le API fornite sono identiche tranne che le versioni a 32 bit hanno parametri ampliati a 32 bit. In Win32, la sicurezza del thread è fornita.

Così almeno sulle finestre, Socket.Accept è sicuro, nel senso che essa non lascerà due thread accettano la stessa connessione thread. Esiste anche un'infrastruttura nell'implementazione ServerSocket (e.g. il metodo Close() usa un lucchetto) che indica che è destinato ad essere thread-safe.

+2

+1 per la risposta dettagliata, ben studiata – talonx

+0

+1 per questa grande risposta – Kartoch

8

Questo non risponde alla domanda, ma l'esecuzione di accept() su più thread suona come se ci fosse qualcosa di sbagliato nel design del server.

In genere non è necessario eseguire accept() da più thread.

Il codice dovrebbe essere simile a questa:

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

Ogni thread di lavoro che accetta la propria connessione è un progetto perfettamente valido. Beneficia di non dover passare ad altri thread. –

+1

Stai pensando ad un threadpool fisso in cui ogni thread compete per accept()? Questa è certamente un'inversione della solita proprietà del thread. Devo ammettere che non riesco a vedere come "il costo del passaggio" a un nuovo thread (o uno da un threadpool) giustificherebbe la complessità nella maggior parte dei casi. Ci sono esempi in cui questo tipo di design è pratico? – Nuoji

+3

Ancora più importante, Java * NON * garantisce la sicurezza del thread di accettare - Il fatto che l'API nativa sottostante faccia in Windows (come citato dalla risposta accettata), non ha senso. –

Problemi correlati