12

ByteBufferスレッドを安全にするためにどのようなオプションが必要ですか?位置、制限、および一部(/すべて?)のメソッドがこの内部状態に依存するため、スレッドセーフではないことが知られています。

私の目的では、複数の読み取りスレッドが安全であれば十分ですが、他の将来の訪問者のために、完全にスレッドセーフにするために知っておく必要のある技術/トリック/トラップを知りたいと思います。

私が念頭に置いていること:

  • すべてのメソッドのReadWriteロックを同期または使用します。おそらく最も遅いアプローチ(?)
  • ByteBufferをサブクラス化し、位置などのスレッドバインド状態を永​​続化しないようにします。内部状態を使用する必要があるすべてのメソッドに応じて例外をスローします。これが断食になります。しかし、トラップはありますか?(直接マップされたメモリをヒープメモリに読み込む必要があることを除いて...)

他にどのようなトリックを使用できますか?たとえば、DirectBufferを使用して「読み取り時にバイトのクローン」を実装するにはどうすればよいですか?それは可能ですか?おそらく、完全なByteBuffer(ByteBuffer.slice)をスライスすることが1つのソリューションに含まれるでしょうか?

更新:この質問「(同期中に)複製して、同じマップされたバイトを指す新しいインスタンスを取得する」とはどういう意味ですか

4

2 に答える 2

13

Buffer クラスはスレッドセーフにすることができます...個々の操作が適切に同期されるなどの意味で。ただし、API は複数のスレッドを考慮して設計されていないため、これはおそらく時間の無駄です。

基本的な問題は、Buffer に対する個々の操作が細かすぎて同期の単位にならないことです。アプリケーションは、get 操作と put 操作、または反転、位置などのレベルで意味のある同期を取ることができません。一般的に言えば、アプリケーションは効果的に同期するために、これらの操作のシーケンスをアトミックに実行する必要があります。

2 つ目の問題は、細かいレベルで同期を行うと、メソッド呼び出しにかなりのオーバーヘッドが追加される可能性が高いことです。バッファ API を使用するポイントは I/O を効率的に行うことであるため、これは目的に反します。


共有バッファへのスレッド アクセスを同期する必要がある場合は、外部同期を使用することをお勧めします。たとえば、次のようなものです。

    synchronized (someLock) {
        buffer.getByte();
        buffer.getLong();
        ...
    }

特定のバッファを使用するすべてのスレッドが適切に同期する (たとえば、同じロック オブジェクトを使用する) 場合、バッファがスレッドセーフでなくても問題ありません。スレッド セーフは、バッファー オブジェクトの外部で、より大まかな方法​​で管理されます。


コメントが指摘しているように、ByteBuffer.slice()orbuffer.asReadOnlyBuffer()を使用して、既存のバッファーをバッキングとして別のバッファーを提供することもできます。ただし、javadoc は、いずれの場合もスレッド セーフを保証しません。実際、Javadocsは次のBuffer包括的なステートメントを作成します。

バッファーは、複数の同時スレッドで使用するのは安全ではありません。バッファが複数のスレッドで使用される場合、バッファへのアクセスは適切な同期によって制御する必要があります。

于 2012-06-22T10:35:03.053 に答える