2012-01-15 8 views
2

複雑なマップがあります。複雑なマップは頻繁に取得されたり、まれにしか変更されないため、ロックされていないため、キーによって参照される要素の動作が一意に決定されます。java:データを公開するためのvolatile配列

つまり、キーが同じ場合、キーが参照する構造体は常に同じ動作をします。実際には、キーは不変finalであり、参照される値は事実上finalおよび/またはthreadsafeです。

私は、カスタムハッシュマップの参照の根本的な揮発性配列への揮発性の参照を持っていると言います。この配列のハッシュマップアルゴリズムはar.lengthメンバーをモジュラスとして使用しているので、get関数で呼び出し元が非現在の配列を参照すると、その参照はすべて良好で、依然としてハッシュスロットに従います。ミューテックスなしで成功し、null以外の値を取得すると、それは正しいものです。

私の計画は、getが失敗するたびに、呼び出し側がキーの正しい値を構築し、他のputとの相対的なロックを行い、オブジェクトを配列に埋め込むputを行います。クリティカルセクションを終了する直前に、putコードは揮発性配列フィールド "ar"を自身に再割り当てします。おそらく、コンパイラとホットスポットコンパイラへのメッセージとして、揮発性配列参照を使用してハッシュ値を検索するgetsに対して相対フェンスを作成します。

これは、限り、コンパイラは「= AR AR」NOPしないように動作します割り当て:揮発性書き込みが離れて最適化することができない

private volatile Object[] ar; 

public Object get (Object key) 
{ 
    Object[] ar = this.ar; 
    // get the value from the correct hash slot 
} 

public synchronized Object put (Object key, Object val) { 
{ 
    ... stuff a new object into the correct hash slot 

    ar = ar;    // will the compiler truly compile this statement with 
         // normal volatile fencing relative to the get function?? 

    ... if a race condition causes a value to already be mapped, return and use that 
    ... rather than the one we created and passed to put (different than normal put 
    ... contract) 
} 

答えて

2

ので、はいあなたは、メモリの保証を取得しますここに。また、配列から値を読み取ると(少なくとも概念的には)、配列のvolatile変数を読み取ると、保証された揮発性読み取りのいずれかを取得する必要があります。

ホットスポットを使用している場合は通常の方法でsun.misc.Unsafeとなります。Java5のコンカレントコレクションを見てみると、そのパターンが十分に頻繁に示されています。 (そして、将来的にはvolatile要素の配列を得ることを楽しみにしています - afaik Doug LeaとCoはそれについての仕様に取り組んでいますが、どれくらい遠いか分かりません)

JDKのConcurrentHashMapと比較して優れた性能を持つCliffの非ブロッキングハッシュマップがあります(かなりの正確性保証があります。

確かに同期化されたput操作よりも速くなります。

関連する問題