c# – 以下线程是否安全?

我有以下代码,并想知道它是否是线程安全的.我只在我从集合中添加或删除项目时锁定,但在迭代集合时不锁定.迭代时锁定会严重影响性能,因为该集合可能包含数十万个项目.有什么建议可以使这个线程安全吗?

谢谢

public class Item
{
    public string DataPoint { get; private set; }

    public Item(string dataPoint)
    {
        DataPoint = dataPoint;
    }
}

public class Test
{
    private List<Item> _items; 
    private readonly object myListLock = new object();

    public Test()
    {
        _items = new List<Item>();
    }

    public void Subscribe(Item item)
    {
        lock (myListLock)
        {
            if (!_items.Contains(item))
            {
                _items.Add(item);
            }
        }
    }

    public void Unsubscribe(Item item)
    {
        lock (myListLock)
        {
            if (_items.Contains(item))
            {
                _items.Remove(item);
            }
        }
    }

    public void Iterate()
    {
        foreach (var item in _items)
        {
            var dp = item.DataPoint;
        }
    }

}

编辑

我很好奇,并且再次在未锁定的迭代与在myListLock上的锁内部迭代之间进行性能分析,并且锁定迭代超过1000万个项目的性能开销实际上非常小.

最佳答案 不,它不是线程安全的,因为当你查看它时可以修改集合……你能做什么:

Item[] items; 

lock (myListLock)
{
    items = _items.ToArray();
}

foreach (var item in items)
{
    var dp = item.DataPoint;
}

所以你在锁之前复制锁中的集合.这显然会使用内存(因为你必须复制List<>)(ConcurrentBag<> .GetEnumerator()几乎就是这样)

请注意,这只有在Item是线程安全的情况下才有效(例如因为它是不可变的)

点赞