2012-05-07 1 views
5

私は、Javaソケットのスレッドセーフは、stackoverflow上のいくつかのスレッドで議論されていることを知っていますが、私はこの質問に明確な答えを見つけることができませんでした - 実際には、複数のスレッドが同時に同じSocketOutputStreamに書き込むか、あるスレッドから送信されたデータが別のスレッドのデータと混ざり合う危険性がありますか? (例えば、相手側の受信側は、あるスレッドのメッセージの最初の半分を受信し、次に別のスレッドのメッセージから残りの最初のスレッドのメッセージを受信する)スレッドセーフティSocketOutputStream

「実際に」と言われた理由は、 Socketクラスはスレッドセーフであるとは言えませんが、現在の実装で実際に安全であれば十分です。私が最も興味を持っている具体的な実装は、Linux上で動作するホットスポットです。

ホットスポットの実装のJavaレイヤー、具体的にはSocketOutputStreamでのsocketWrite()の実装を見ると、socketWrite0()のネイティブ実装が安全である限りスレッドセーフであるように見えます。しかし、その方法(j2se/src/solaris/native/java/net/SocketOutputStream.c)の実装を見ると、送信されるデータは64または128kbのチャンクに分割されているようです(64ビットJVM)し、別々の書き込みでチャンクを送信します。

私には、異なるスレッドから64kb以上を送信するのは安全ではないようですが、64kb未満であれば安全であるはずですが、ここで重要なものが欠落している可能性があります。ここに他の誰かがこれを見て、別の結論に来ましたか?

答えて

5

実際にはだと思います。あなたのコントロールを超えて変わる可能性のある実装の詳細に大きく依存するのは悪い考えです。このようなことをすれば、非常に慎重にバージョンのすべてを制御する必要があります。あなたが期待していることを確認するために使用するのは非常に難しいことです。そして、あなたのソリューションのStackOverflow上のランドムからのコード検査と噂に依存しているので、マルチスレッドのオペレーションが正しく機能することを検証するための非常に頑強なテストスイートが必要です。

SocketOutputStreamを別のパススルーOutputStreamにラップして、そのレベルで必要な同期を追加できないのはなぜですか?このようにする方がはるかに安全で、予期しない問題が発生する可能性は非常に低いです。

+1

..あなたはプロデューサー(書き込みが)に追加することをBlockingDequeとプロデューサ/コンシューマモデルを持っている可能性があり、消費者(送信者)が送信するために、フロントオフのものを引っ張ります。 – sjr

+0

お返事いただきありがとうございます。それが良い考えかどうかは議論の余地があります。個人的には、特定の実装に依存していることを行うことは、必然的にアイデアが悪いとは思わない。 "どこでも実行する"というアイデアの他に、javaを使いたい理由がたくさんある。パフォーマンスが重大である場合、実装上でコードを実行できることは、あなたが落としたいと考える要件です。 – oscar11

+0

私は、書き込みの周りにロックを追加するか、別個のスレッドを使用して1つのライターしか存在しないことを知っています。ブロッキングキューは問題を「解決」します。ブロッキングキューを使用すると、残念ながら私の要件には余裕がありますが、書き込みへのアクセスを同期させると実際には安全になりますが、実際には必要ない場合は避けるのが良いでしょう。 – oscar11

2

このドキュメントhttp://www.docjar.com/docs/api/java/net/SocketOutputStream.htmlによれば、クラスはスレッドセーフであると主張しないため、そうではないと想定します。 FileOutputStreamを継承します。FileOutputStreamは通常、ファイルI/Oは本質的にスレッドセーフではありません。

私のアドバイスは、クラスがハードウェアや通信に関連している場合、スレッドセーフでも「ブロック」でもないことです。その理由は、スレッドセーフな操作は時間がかかります。私の背景はJavaではありませんが、他の図書館は哲学において似ています。

私はクラスを広範にテストしていることに気づきましたが、何日も何日間もテストしても、2セントで何も証明できないことがあります。

幸運&楽しんでください。合意

トミーKwee

関連する問題