我有一个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.