6


1

ソケットの入力と出力に別々のスレッド

マルチスレッドJavaサーバーのパフォーマンスとランダムなクラッシュの問題に取り組むことになりました。 スレッドとスレッドセーフは私にとって新しいトピックではありませんが、新しいマルチスレッドアプリケーションの設計は、おそらくレガシーコードを微調整するのと比べて半分ほど難しいことがわかりました。 答えを求めていくつかの有名な本をざっと読みましたが、奇妙なことは、それについて読んで、提供された例を分析する限り、すべてがはっきりしているようです。 ただし、2番目に作業するコードを見ると、もう何もわからないのです! 理論的知識が多すぎて、現実世界での経験がほとんどないか、何かである必要があります。

とにかく、トピックに戻って、オンラインで調査を行っていたときに、https://stackoverflow.com/questions/511552/reading-from-a-socket-not-waiting-for-input [* thisコードの一部*]。 私を悩ませ続ける質問は次のとおりです:* 2つの別々のスレッドからソケットのgetInputStream()およびgetOutputStream()を同期せずに呼び出すことは本当に安全ですか?*または、スレッドセーフの問題全体について少し偏執的になっていますか? 連続する5番目の本のように、並行処理で問題が発生する可能性のあるものがいくつあるかがわかると、それが起こると思います。

PS. 質問が長すぎたり、多分「ヌービー」だったらごめんなさい。簡単に聞いてください-これが私の最初の投稿です。

*編集:*明確にするために、ソケットは全二重モードで動作することを知っており、入出力ストリームを同時に使用しても安全です。 メインスレッドでこれらの参照を取得し、それらを使用してスレッドオブジェクトを初期化すると、私には問題ないようですが、これらのストリームを2つの異なるスレッドで_get_しても安全ですか?

  • @ rsp:*

だから私はSunのコードをチェックし、 `PlainSocketImpl`はあなたが言ったようにそれらの2つのメソッドで同期します。 ただし、「ソケット」はサポートしません。 `getInputStream()`と `getOutputStream()`は `SocketImpl`の単なるラッパーにすぎないので、_同時性の問題が原因でサーバー全体が爆発することはありません。 それでも、少し不運なタイミングで、物事がうまくいかないように思えます(例: メソッドがすでにエラー状態をチェックしているときに、他のスレッドがソケットを閉じたとき)。

あなたが指摘したように、コード構造の観点から、ソケット全体ではなくストリーム参照を各スレッドに提供することをお勧めします。 各スレッドもソケットの `close()`メソッドを使用しているという事実がない場合は、おそらく作業中のコードをすでに再構築しているでしょう。 ソケットが「シャットダウン」コマンドを受信したとき)。 私の知る限り、これらのスレッドの主な目的は、送信または処理のためにメッセージをキューに入れることです。したがって、おそらく単一責任原則違反であり、これらのスレッドはソケットを閉じることができません(http://と比較してください) www.objectmentor.com/resources/articles/srp.pdf[Separated Modem Interface])? しかし、もしコードを分析し続ける時間が長すぎると、デザインに一般的に欠陥があり、全体を書き直す必要があるように見えます。 経営陣が代価を払っても構わないと思っていたとしても、従来のコードを真剣にリファクタリングし、単体テストを一切行わず、並行性の問題をデバッグするのが難しいとしたら、おそらく害よりも害になるでしょう。 そうではないですか?

1 Answer


3


ソケットの入力ストリームと出力ストリームは、2つの別個のデータストリームまたはチャネルを表します。 スレッド間で同期されていないスレッドで両方のストリームを使用すると、完全に節約されます。 ソケットストリーム自体は、空または満杯のバッファでの読み取りと書き込みをブロックします。

編集:Sunのソケット実装クラスは、 `getInputStream()`メソッドと `getOutputStream()`メソッドを同期します。異なるスレッドからの呼び出しは問題ありません。 ただし、ストリームを使用してスレッドにストリームを渡すことは、コード構造の観点からより理にかなっているかもしれません(依存性注入は、たとえばテストに役立ちます)。