エントリを挿入して、エントリがすでに挿入されているかどうかをすばやく判断できるデータ型が必要です。 Dictionary
はこのニーズに適しているようです(例を参照)。しかし、私は辞書のvalues
を使用していません。それでも辞書を使用する必要がありますか、それともより適切なデータ型がありますか?
public class Foo
{
private Dictionary<string, bool> Entities;
...
public void AddEntity(string bar)
{
if (!Entities.ContainsKey(bar))
{
// bool value true here has no use and is just a placeholder
Entities.Add(bar, true);
}
}
public string[] GetEntities()
{
return Entities.Keys.ToArray();
}
}
HashSet<T>
クラスは、高性能な集合演算を提供します。セットとは、重複する要素が含まれておらず、要素が特定の順序になっていないコレクションです。
ハビブの答え は優れていますが、マルチスレッド環境でHashSet<T>
を使用する場合、その結果、lock
sを使用してアクセスを保護する必要があります。 lock
ステートメントを使用してデッドロックを作成する傾向があります。また、lock
sは アムダールの法則 に従ってスピードアップを悪化させます。これは、lock
ステートメントを追加すると、実際に並列であるコードの割合が減少するためです。
これらの理由により、a ConcurrentDictionary<T,object>
はマルチスレッド環境の要件に適合します。使用する場合は、質問で行ったようにラップしてください。値は重要ではないので、必要に応じてnew
up object
sを必要に応じてトスしてください。 ソースコード に。lock
ステートメントがないことを確認できます
コレクションの可変性が必要なかった場合、これは意味がありません。しかし、あなたの質問は、あなたがAddEntity
メソッドを持っているので、あなたがそれを必要とすることを意味します。
追加情報2017-05-19-実際には、ConcurrentDictionary
does内部でロックを使用します、ただしlock
ステートメント自体ではありません-Monitor.Enter
を使用します( TryAddInternal
を確認してください方法)。ただし、ディクショナリ内の個々のバケットがロックされるようです。つまり、lock
ステートメントに全体を配置するよりも競合が少なくなります。
したがって、全体として、ConcurrentDictionary
はマルチスレッド環境に適しています。
Interlocked メソッドのみを使用して並行ハッシュセットを作成することは、実際には非常に困難です(不可能ですか?)。私は自分で試してみましたが、同時に2つのことを変更する必要があるという問題に遭遇し続けました-一般的にロックだけができること。私が見つけた1つの回避策は、ハッシュバケットに単一リンクリストを使用し、1つのスレッドが他のスレッドからの干渉なしにノードを操作する必要がある場合に、リストにサイクルを意図的に作成することでした。これにより、そのノードがノードで実行されてサイクルが元に戻されるまで、他のスレッドが同じ場所でスピンし続けます。もちろん、技術的にはロックを使用していませんが、適切に拡張できませんでした。