Блокировка необходима для поиска словаря?
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
или, возможно, объект, который не соответствует ключу.
Это только одна вещь, которая может случиться. Что-то подобное катастрофическое может произойти, если вы просматриваете один поток, а другой поток добавляет значение, которое вы пытаетесь найти.
Ответ 5
Используйте новый объект ConcurrentDictionary<TKey, TValue>
, и вы можете забыть о необходимости делать блокировки.
Ответ 6
Да, вам нужно заблокировать словарь для доступа в многопоточной среде. Запись в словарь не является атомарной, поэтому она может добавить ключ, но не значение. В этом случае при доступе к нему вы можете получить исключение.
Ответ 7
Если вы находитесь на .Net 4, вы можете заменить ConcurrentDictionary, чтобы сделать это безопасно. Существуют и другие подобные коллекции, предпочтительные, когда вам нужен многопоточный доступ, в пространстве имен System.Collection.Concurrent.
Не используйте рулонную блокировку, если это вариант для вас.
Ответ 8
Да, вы должны заблокировать, если этот словарь является общим ресурсом между несколькими потоками. Это гарантирует, что вы получите правильное значение, а другой поток не изменит значение в середине вашего вызова Lookup.
Ответ 9
Да, вы должны заблокировать, если в этом словаре есть многопоточные обновления. Для получения дополнительной информации см. Этот отличный пост: Словарь "Безопасный поток" (TKey, TValue)
Но так как ConcurrentDictionary < > , вы можете использовать его либо через .NET 4, либо используя Rx в 3.5 (он содержит System.Threading.dll с реализацией для новых потокобезопасных коллекций)