Вопрос:

блокировка необходима для поиска в словаре?

c# multithreading dictionary locking lookup

8454 просмотра

9 ответа

24449 Репутация автора

lock(dictionaryX)
{
   dictionaryX.TryGetValue(key, out value);
}

блокировка необходима при поиске в словаре?

Программа многопоточная, и при добавлении ключ / значение в dict. Дикт заблокирован.

Автор: DarthVader Источник Размещён: 22.10.2010 07:38

Ответы (9)


2 плюса

610490 Репутация автора

Решение

Блокировка необходима только при синхронизации доступа к ресурсу между потоками. Пока не задействовано несколько потоков, блокировка здесь не требуется.

В контексте обновления и чтения значения из нескольких потоков, да, блокировка абсолютно необходима. Фактически, если вы используете 4.0, вам следует рассмотреть возможность перехода на одну из коллекций, специально предназначенных для одновременного доступа.

Автор: JaredPar Размещён: 22.10.2010 07:40

0 плюса

11097 Репутация автора

Да, вам следует заблокировать, если этот словарь является общим ресурсом для нескольких потоков. Это гарантирует, что вы получите правильное значение, и другой поток не сможет изменить значение на полпути во время вашего вызова Lookup.

Автор: Aamir Размещён: 22.10.2010 07:43

12 плюса

15639 Репутация автора

Как уже упоминалось здесь :

Использование TryGetValue () без блокировки небезопасно. Словарь временно находится в состоянии, которое делает его непригодным для чтения, пока другой поток пишет словарь. Словарь будет реорганизовываться время от времени по мере увеличения количества записей в нем. Когда вы читаете в точное время, когда происходит реорганизация, вы рискуете найти неправильное значение для ключа, когда корзины обновлены, но еще не введены значения.

ОБНОВЛЕНИЕ: взгляните на часть «Безопасность потоков» на этой странице .

Автор: Kamyar Размещён: 22.10.2010 07:44

1 плюс

56286 Репутация автора

Да, вам необходимо заблокировать словарь для доступа в многопоточной среде. Запись в словарь не является атомарной, поэтому он может добавить ключ, но не значение. В том случае, когда вы получаете к нему доступ, вы можете получить исключение.

Автор: Yuriy Faktorovich Размещён: 22.10.2010 07:45

4 плюса

17815 Репутация автора

Как и во многих тонких вопросах программирования, ответ таков: не обязательно.

Если вы только добавляете значения в качестве инициализации, то последующее чтение не нужно синхронизировать. Но, с другой стороны, если вы собираетесь постоянно читать и писать, тогда вам абсолютно необходимо защитить этот ресурс.

Тем не менее, полноценный lockможет быть не лучшим способом, в зависимости от объема трафика, который получает ваш словарь. Попробуйте, ReaderWriterLockSlimесли вы используете .NET 3.5 или выше.

Автор: Jesse C. Slicer Размещён: 22.10.2010 07:46

3 плюса

111104 Репутация автора

Если у вас есть несколько потоков, обращающихся к Словарю, вам нужно заблокировать обновления и поиск. Причина, по которой вам нужно заблокировать поиск, заключается в том, что обновление может происходить в то же время, когда вы выполняете поиск, а Словарь может находиться в несовместимом состоянии во время обновления. Например, представьте, что у вас есть один поток, который делает это:

if (myDictionary.TryGetValue(key, out value))
{
}

и отдельный поток делает это:

myDictionary.Remove(key);

TryGetValueМожет случиться так, что поток, который выполняет определение, определяет, что элемент находится в словаре, но прежде чем он сможет извлечь элемент, другой поток удаляет его. В результате поток, выполняющий поиск, либо выдаст исключение, либо TryGetValueвернет, trueно valueбудет nullили, возможно, объектом, не соответствующим ключу.

Это только одна вещь, которая может случиться. Нечто подобное может произойти, если вы выполняете поиск в одном потоке, а другой поток добавляет значение, которое вы пытаетесь найти.

Автор: Jim Mischel Размещён: 22.10.2010 07:49

1 плюс

47823 Репутация автора

Если вы используете .Net 4, вы можете заменить его на ConcurrentDictionary, чтобы сделать это безопасно. В пространстве имен System.Collection.Concurrent есть и другие похожие коллекции, предпочтительные, когда вам нужен многопоточный доступ .

Не используйте блокировку «по-своему», если это вариант для вас.

Автор: Steve Townsend Размещён: 22.10.2010 08:33

2 плюса

2317 Репутация автора

Используйте новый ConcurrentDictionary<TKey, TValue>объект, и вы можете забыть о необходимости делать какие-либо блокировки.

Автор: SnickersAreMyFave Размещён: 22.10.2010 10:49

0 плюса

4005 Репутация автора

Да, вы должны заблокировать, если у вас есть многопоточные обновления в этом словаре. Проверьте этот великий пост для деталей: словарь «Безопасный поток» (TKey, TValue)

Но с тех пор как появился ConcurrentDictionary <>, вы можете использовать его либо через .NET 4, либо с помощью Rx в 3.5 (он содержит System.Threading.dll с реализацией для новых многопоточных коллекций)

Автор: Nick Martyshchenko Размещён: 23.10.2010 01:15
Вопросы из категории :
32x32