我正在试图找出一个最好的方法来拥有一个我将能够迭代的集合,添加项目并同时从不同的线程中删除所有项目。性能对于迭代组件至关重要,但不会经常添加和删除项目 - 因此添加/删除性能的重要性稍差。
以下是我提出的建议:
public class AtomicList<T> : IEnumerable<T>
{
private readonly object Locker = new object();
private List<T> InternalCollection = new List<T>();
public void Add(T Value)
{
lock (Locker)
{
List<T> Update = new List<T>(InternalCollection);
Update.Add(Value);
InternalCollection = Update;
}
}
public void Remove(T Value)
{
lock (Locker)
{
List<T> Update = new List<T>(InternalCollection);
Update.Remove(Value);
InternalCollection = Update;
}
}
public IEnumerator<T> GetEnumerator()
{
return InternalCollection.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
这样做有什么缺点吗?有没有像我上面描述的那样线程安全/可迭代的情况?
此外 - 使用foreach和IEnumerable有任何性能成本吗?如果我直接访问InternalCollection并对其进行for语句会更好吗?
答案 0 :(得分:3)
如果不同时调用Add和Remove方法,则不需要lock
,因为您只读取InternalCollection
字段引用的列表。使用Interlocked.Exchange Method以线程安全的方式将旧列表替换为新列表:
public class AtomicList<T> : IEnumerable<T>
{
private List<T> internalCollection = new List<T>();
public void Add(T vlue)
{
List<T> update = new List<T>(internalCollection);
update.Add(value);
Interlocked.Exchange(ref internalCollection, update);
}
public bool Remove(T value)
{
List<T> update = new List<T>(internalCollection);
bool removed = update.Remove(value);
if (removed) Interlocked.Exchange(ref internalCollection, update);
return removed;
}
public IEnumerator<T> GetEnumerator()
{
...