блокировка необходима для поиска в словаре? - PullRequest
11 голосов
/ 22 октября 2010
lock(dictionaryX)
{
   dictionaryX.TryGetValue(key, out value);
}

требуется ли блокировка при поиске в словаре?

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

Ответы [ 9 ]

11 голосов
/ 22 октября 2010

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

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

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

4 голосов
/ 22 октября 2010

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

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

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

3 голосов
/ 22 октября 2010

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

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

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

myDictionary.Remove(key);

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

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

2 голосов
/ 23 октября 2010

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

2 голосов
/ 22 октября 2010

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

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

1 голос
/ 23 октября 2010

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

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

1 голос
/ 22 октября 2010

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

0 голосов
/ 23 октября 2010

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

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

0 голосов
/ 22 октября 2010

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

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