当多个线程尝试增加int时,我遇到了问题。这是我的代码:
private int _StoreIndex;
private readonly List<Store> _Stores = new List<Store>();
public void TestThreads()
{
_StoreIndex = 0;
for (int i = 0; i < 20; i++)
{
Thread thread = new Thread(() =>
{
while (_StoreIndex < _Stores.Count - 1)
{
_Stores[Interlocked.Increment(ref _StoreIndex)].CollectData();
}
});
thread.Start();
}
}
我希望每次线程执行此代码时int增加1。但事实并非如此。我也尝试过使用lock(new object()),但这也不行。问题是并非所有商店都收集数据,因为(调试时),_StoreIndex就像0,1,1,3,4,5一样。显然会跳过列表中的第二个对象。
我做错了什么?提前谢谢。
答案 0 :(得分:4)
在你的情况下,我会首先使用TPL来避免手动线程创建和索引的所有这些问题:
Parallel.ForEach(_Stores, (store) => store.CollectData());
答案 1 :(得分:3)
我认为应该纠正:
Thread thread = new Thread(() =>
{
int index = 0;
while ((index = Interlocked.Increment(ref _StoreIndex)) < _Stores.Count - 1)
{
_Stores[index].CollectData();
}
});
现在索引是本地的,所以没有干扰,而_StoreIndex仅在一个地方以原子方式使用。
答案 2 :(得分:1)
这不是原子操作:
_Stores[Interlocked.Increment(ref _StoreIndex)].CollectData();
增量是原子的,但是这一行包含的代码多于简单的增量。您可能需要首先对您的indeces进行排序,然后使用线程安全集合来保存您的商店,例如ConcurrentBag,并且可能会考虑使用TPL库和类Task
和Parallel
来执行工作负载。