c# - 这种使用通用 List 线程安全吗

标签 c# .net thread-safety

我有一个 System.Collections.Generic.List<T>我只在计时器回调中添加项目。只有在操作完成后才会重新启动计时器。

我有一个 System.Collections.Concurrent.ConcurrentQueue<T>它存储上面列表中添加项目的索引。此存储操作也始终在上述相同的计时器回调中执行。

遍历队列并访问列表中相应项的读取操作线程安全吗?

示例代码:

private List<Object> items;
private ConcurrentQueue<int> queue;
private Timer timer;
private void callback(object state)
{
    int index = items.Count;
    items.Add(new object());
    if (true)//some condition here
        queue.Enqueue(index);
    timer.Change(TimeSpan.FromMilliseconds(500), TimeSpan.FromMilliseconds(-1));
}

//This can be called from any thread
public IEnumerable<object> AccessItems()
{
    foreach (var index in queue)
    {
        yield return items[index];
    }
}

我的理解: 即使列表在被索引时调整了大小,我也只是访问一个已经存在的项目,所以无论是从旧数组还是从新数组读取都没有关系。因此这应该是线程安全的。

最佳答案

Is a read operation that iterates the queue and accesses the corresponding items in the list thread safe?

它是否记录是线程安全的?

如果不是,那么将它视为线程安全是愚蠢的,即使它是偶然地在这个实现中也是如此。线程安全应该设计

首先,跨线程共享内存是个坏主意;如果您不这样做,那么您不必询问该操作是否是线程安全的。

如果您必须这样做,请使用专为共享内存访问而设计的集合。

如果您不能这样做,则使用锁。如果没有竞争,锁很便宜。

如果您遇到性能问题,因为您的锁一直处于争用状态,那么通过更改您的线程架构来解决该问题,而不是尝试做低锁代码等危险和愚蠢的事情。除了少数专家,没有人能正确编写低锁代码。 (我不是他们中的一员;我也不写低锁代码。)

Even if the list is resized when it is being indexed, I am only accessing an item that already exists, so it does not matter whether it is read from the old array or the new array.

这是错误的思考方式。正确的思考方式是:

If the list is resized then the list's internal data structures are being mutated. It is possible that the internal data structure is mutated into an inconsistent form halfway through the mutation, that will be made consistent by the time the mutation is finished. Therefore my reader can see this inconsistent state from another thread, which makes the behaviour of my entire program unpredictable. It could crash, it could go into an infinite loop, it could corrupt other data structures, I don't know, because I'm running code that assumes a consistent state in a world with inconsistent state.

关于c# - 这种使用通用 List 线程安全吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15052523/

相关文章:

multithreading - java :singleton, 静态变量和线程安全

c++ - 这段代码是线程安全的吗?

c# - 检测到 ThreadPool WorkItem 已完成/等待完成

c# - 在 C++ 中是否有与 C# Structs/StructLayout 具有字段偏移的等效功能?

c# - 显式转换 XAttribute 值

c# - 多核编程 : the hard parts

c - 中断安全缓冲区

c# - 如何从 ViewModel 访问 View 控件?

c# - 允许自定义控件正确滚动出 View

c# - Microsoft.WindowsAzure.Storage 和 System.Net.Http 冲突