0

Java nio に依存するサーバーの実装では、次の慣行が標準のようです。

読み取りには単一のスレッド (および単一のセレクター) を使用します。

ByteBuffer buffer = . . .
selector.select()
...
channel.read(buffer)
if (isRequestComplete(buffer))
    processRequest(buffer) //will run in a separate thread

void processRequest(ByteBuffer buffer)
    new Thread(new Handler(buffer)).start()

はい、かなりの量のコードを省略しています

私の質問は、チャネルからの選択/読み取りの仕組みに関するものではなく、#buffer がセレクター スレッドとは別のスレッドで読み取られるという可視性のセマンティクスに関するものです。スレッド A (上記の「ハンドラー」) の ByteBuffer からの読み取りは、スレッド B (上記の「セレクター」) の ByteBuffer への書き込みを確認することが保証されていることを示す javadoc には何も表示されません。
さて、上記のコードは単純にマルチスレッドセーフではないように思えます。つまり、間違っています。しかし、私は多数のチュートリアルや一部のコードベースで同じパターンを見てきました (常に可視性の問題を参照することさえありません)。明らかな何かが欠けているのではないかと思っています。

注: 私は特に、「ハンドラー」スレッドが #buffer からのみ読み取る状況に焦点を当てています。新しいバイトを書き込むことはありません。

4

1 に答える 1

1

これは実際には問題ないようです。必要なのは、セレクタースレッドでの書き込みが、ハンドラースレッドでの読み取りの「前に発生する」ことを証明することです。メモリの可視性のルールに従って、同じスレッド内のアクションはプログラムの順序で発生します。新しいスレッドを作成すると、事前発生も確立されます。したがって、書き込みは読み取りの前に発生するスレッド作成の前に発生します。

これは、たとえば an に渡しても問題ありませんExecutorService

于 2013-03-17T06:15:11.300 に答える