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

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

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

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

Ответ 1

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

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

Ответ 2

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

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

UPDATE: взгляните на "Thread Safety" часть на этой странице.

Ответ 3

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

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

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

Ответ 4

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

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

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

myDictionary.Remove(key);

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

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

Ответ 6

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

Ответ 7

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

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

Ответ 8

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

Ответ 9

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

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