多个线程增加int

本文关键字:int 增加 线程 | 更新日期: 2023-09-27 18:16:10

我有一个问题,当多个线程试图增加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一样。列表中的第二个对象显然被跳过了。

我做错了什么?

多个线程增加int

在您的情况下,我会首先使用TPL来避免手动创建线程和索引的所有这些问题:

Parallel.ForEach(_Stores, (store) => store.CollectData());

我认为应该更正为:

Thread thread = new Thread(() =>
{
    int index = 0;
    while ((index = Interlocked.Increment(ref _StoreIndex)) < _Stores.Count - 1)
    {
         _Stores[index].CollectData();
    }
});

现在index是本地的,所以没有干扰,而_StoreIndex只在单个位置自动使用

这不是原子操作:

_Stores[Interlocked.Increment(ref _StoreIndex)].CollectData();

Increment是原子的,但是这一行包含的代码比简单的Increment多。您可能需要首先对索引进行排序,然后使用线程安全收集来保存存储,例如ConcurrentBag,并且可能考虑TPL库和类(例如TaskParallel)来执行工作负载。