2009-05-22 16 views
11

学校プロジェクトでは、Java 5.0でマルチスレッドサーバーを作成しています。このプロジェクトは、サーバーの同意の側面を中心としています。Java:ServerSocket.acceptはスレッドセーフですか?

私たちには、リクエストの処理専用のスレッドがあります。そうするために、新しい接続を受け入れるためにServerSocket.accept()を呼び出す。私たちの選択は、それらの束を開始し、2つのスレッドが同じ接続を同時に受け入れることができないという仮定で、着信接続を処理させることでした。

しかし、現在の主な問題は、この動作を保証するもの(またはわれわれが正しく見なかったもの)をAPIで見つけることができず、「それは機能する」という証明以外は何もありません。

Javaメソッドに関するこの種の情報を探すソースがありますか?

+0

このデザインはあまりうまくいかず、ワーカースレッドのプールを使用するように変更しました。これで、要求を受け付けてワーカースレッドに送信するスレッドが1つしかありません。 Javaメソッドのスレッドセーフに関する情報があるかどうかはまだわかります。 –

答えて

25

短い答えを:ドキュメントは何かがスレッドセーフであることを指定しない場合、あなたはそれがないと仮定しなければなりません。同時に2つのスレッドがサーバソケットを同時に使用しないように、スレッド間の調整を自分で行う必要があります。

他のコードが独自のソケット実装をServerSocket.setSocketFactoryに登録している可能性があるため、これは特に重要です。デフォルトのソケット実装がスレッドセーフであっても、カスタム実装は必須ではありません。そのように書かれている文書はありません。

長い答え:デフォルトのWindowsの実装

あなたはjava SE 1.6 source codeをダウンロードして調べることができます。

私は\j2se\src\share\classes\java\net\ServerSocket.javaで開始し、そこからトレイルがPlainSocketImpl.javaになりました。 PlainSocketImpl.Acceptメソッドはnativeとマークされています。

WindowsのネイティブC++コードは\j2se\src\windows\native\java\net\PlainSocketImpl.cです。それはwinsock accept機能を使用します。 MSDN article on WinSock(強調鉱山)から:

のWindows NTおよびWindows 2000の下では、16ビット アプリケーション用 WindowsソケットのサポートはWINSOCK.DLLに基づいています。 32ビットアプリケーションの場合、 のサポートはWSOCK32.DLLにあります。提供されるAPIは であり、32ビットの バージョンのパラメータは32 ビットに拡大されています。 Win32では、スレッドの安全性は です。

だから、少なくともWindows上で、Socket.Acceptは、それが2つのスレッドが同じ接続を受け入れることはできませんという意味では、スレッドセーフです。実装にはインフラストラクチャーも存在する(例えば、http:// www。g。 Close()メソッドはスレッドセーフであることを示すロックを使用します)。

+2

詳細については、よく研究された答え – talonx

+0

+1この素晴らしい答え – Kartoch

8

これはあなたの質問にはあまり答えませんが、複数のスレッドで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(); 
} 
+0

独自の接続を受け付ける各ワーカースレッドは、完全に有効な設計です。それは他のスレッドに引き渡す必要がないことから利益を得ます。 –

+1

あなたは、各スレッドがaccept()のために競合する固定スレッドプールを考えていますか?これは確かに通常のスレッドの所有権を逆転させたものです。私は、新しいスレッド(またはスレッドプールからの)への「引き渡しのコスト」がどのようにしてほとんどの場合複雑さを正当化するのかわかりません。この種のデザインが実用的な例はありますか? – Nuoji

+3

もっと重要なのは、Javaはacceptのスレッドの安全性を保証していないことです。(受け入れられた回答で引用されているように)元のネイティブAPIがWindowsで行うことは無意味です。 –

関連する問題