0

完全に機能する Java オブジェクトのプールを作成するために、READ/WRITE ロックを使用することは大きな問題ではありません。私が見ている問題は、ストレージ モニター (またはモデルによっては同様のもの) が解放されるまで READ 操作を待機する必要があり、実際に速度が低下することです。

したがって、次の要件を満たす必要があります。

  1. READ (または GET) 操作は INSTANT である必要があります。何らかのキーを使用すると、ロックを待たずにオブジェクトの最新バージョンがすぐに返されます。

  2. WRITE (CREATE/UPDATE) - キューに入れられ、かなり遅れて、おそらく何らかのストレージ ロックを待っている可能性があります。

コードサンプルはありますか?


この問題を直接対象とする質問は見つかりませんでした。

いくつかの議論で出てきましたが、Java でそのようなプールを作成する際の問題に完全に専念した質問を見つけることができませんでした。

4

3 に答える 3

0

データ構造の変更に時間がかかりすぎる場合 (何らかの理由で)、単純に待機して構造を書き込みロックしても成功しません。読み取りをブロックせずに変更を実行するのに十分な時間がいつあるかを予測することはできません。

あなたができる(やろうとする)唯一のことは、書き込み操作の時間を最小限に抑えることです。@assylias が述べたように、CopyOnWrite* は書き込み操作時にデータ構造を複製することでこれを行い、操作が完了すると変更された構造をアトミックにアクティブ化します。

これにより、読み取りロックには、クローン操作の期間と参照の切り替えにかかる時間と同じだけの時間がかかります。データ構造の小さな部分まで作業できます。オブジェクトの状態のみが変更された場合、そのオブジェクトのコピーを変更し、後でより複雑なデータ構造の参照をそのコピーに変更できます。

もう 1 つの方法は、読み取り操作時または読み取り操作の前にそのコピーを実行することです。いずれにせよ、データ構造の API を介してオブジェクトのコピーを返すことがよくあるため、そのコピーを「キャッシュ」し、変更中にリーダーがキャッシュされたコピーにアクセスできるようにします。これは、データベースキャッシュ aso が行うことです。

何が最適かは、モデルによって異なります。簡単にコピーできるデータへの書き込みがほとんどない場合は、CopyOnWrite が最適なパフォーマンスを発揮する可能性があります。書き込みが多い場合は、構造の単一の「読み取り」/キャッシュ状態を提供し、時々切り替えることをお勧めします。

AtomicReference<Some> datastructure = ...; 

//copy on write

synchronized /*one writer*/ void change(Object modification) 
throws CloneNotSupportedException {
   Object copy = datastructure.clone();
   apply(copy, modification);
   datastructure.set(copy);  
}

Object search(Object select) {
   return datastructure.get().search(select);
}

// copy for read

AtomicReference<Some> cached = new AtomicReference<Some>(datastructure.get().clone());

synchronized void change(Object modification) {
    apply(datastructure, modification);
    cached.set(datastructure);
}

Object search(Object select) {
    return cached.get().search(select);
}

どちらの操作でも、読み取り時に待機はありませんが、参照を切り替える必要がある間は待機します。

于 2013-04-01T09:17:55.427 に答える