Что произойдет, если две ссылки попытаются добавить данные в одно и то же время в список List <T> - PullRequest
0 голосов
/ 29 февраля 2012

Проверьте эту функцию.

private static IEnumerable<string> FindAccessibleDatabases()
{
    var connectionStrings = new List<string>();
    Parallel.For(0, _connectionStringCollection.Count, (index, loopState) =>
    {
        try
        {
            using (var connection = new OleDbConnection(_connectionStringCollection[index]))
            {
                connection.Open();
                connectionStrings.Add(_connectionStringCollection[index]);
            }
        }
        catch (OleDbException)
        {
        }
        finally         
        {
           connection.Close();
        }
    });
    return connectionStrings.ToList();
}

Я использую Parallel.Foreach и добавляю значения в список из нескольких баз данных одновременно. Я могу использовать ConcurrentBag (это безопасно при извлечении данных, но добавление не упоминается), так как я просто добавляю данные в список, могу использовать List.

Теперь, если два потока попытаются добавить данные в список одновременно, что произойдет?

Если это создаст условия гонки, что если я использую ConcurrentBag?

Спасибо, Omkar

1 Ответ

5 голосов
/ 29 февраля 2012

Вы рискуете неустановленных плохих вещей , таких как дубликаты, не добавление одного элемента, повреждение структуры данных и т. Д.

В документации говоритсячто метод Add List<T> не является потокобезопасным (ну, в частности, он говорит:

A List<T> может поддерживать несколько считывателей одновременно, пока коллекция не изменена. Перечисление посредствомколлекция по своей сути не является потокобезопасной процедурой. В редком случае, когда перечисление конкурирует с одним или несколькими доступами на запись, единственный способ обеспечить безопасность потока - это заблокировать коллекцию в течение всего перечисления.несколько потоков для чтения и записи, вы должны реализовать собственную синхронизацию.

).Поэтому вам нужно использовать оператор блокировки или другую форму синхронизации потоков вокруг него, или вам нужно переключиться на многопоточную структуру данных, как что-то в System.Collections.Concurrent namespace.

Если вы используете метод Add ConcurrentBag, вам не нужно беспокоиться о блокировке.Структура данных явно поточно-ориентированная.

...