Несколько потоков увеличивается int - PullRequest
1 голос
/ 30 ноября 2011

У меня проблема, когда несколько потоков пытаются увеличить 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 увеличивается на единицу каждый раз, когда поток выполняет этот код.Однако это не так.Я также пытался использовать блокировку (новый объект ()), но это не работает так же хорошо.Проблема заключается в том, что не все хранилища собирают данные, потому что (при отладке) _StoreIndex выглядит, например, как 0, 1, 1, 3, 4, 5.Второй объект в списке явно пропущен.

Что я делаю не так?Заранее спасибо.

Ответы [ 3 ]

4 голосов
/ 01 декабря 2011

В вашем случае я бы использовал TPL, чтобы избежать всех этих проблем с ручным созданием потока и индексами в первую очередь:

Parallel.ForEach(_Stores, (store) => store.CollectData());
3 голосов
/ 01 декабря 2011

Я думаю, это должно быть исправлено на:

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

Теперь индекс локальный, поэтому помех нет, а _StoreIndex используется только атомарно в одном месте.

1 голос
/ 01 декабря 2011

Это не атомарная операция:

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

Приращение является атомарным, но эта строка содержит больше кода, чем простое приращение.Возможно, вам придется сначала отсортировать ваши индексы, а затем использовать потокобезопасную коллекцию для хранения ваших магазинов, например ConcurrentBag, и, возможно, рассмотреть библиотеку TPL и классы, такие как Task и Parallel, для выполнения рабочей нагрузки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...