Конкретная блокировка словаря
В настоящее время я читаю код, предоставленный нашим внешним человеком, и я не понимаю эту часть кода:
private ConcurrentDictionary<Int64, Person> users = new ConcurrentDictionary<Int64, Person>();
private Dictionary<String, Int64> connectionIndex = new Dictionary<String, Int64>();
public Boolean AddNewUser(Int64 userId, Person user) {
Boolean added = false;
lock (users) {
if (users.Select(X=>X.Key==userId).Count()>0)
{
Person usrtmp = new Person();
users.TryRemove(userId,out usrtmp)
}
added = users.TryAdd(userId, user);
if (added)
{
connectionIndex.Add(user.ConnectionId, userId);
}
}
return added;
}
Почему "словарь одновременного использования пользователями" блокируется перед выполнением какой-либо операции над этим словарем? Это необходимо? С моей точки зрения, оператор блокировки не нужен, потому что ConcurrentDictionary содержит поточно-ориентированные операции. Я прав? Кроме того, я знаю о "проблеме производительности", когда вы используете операции.Count() или Key, Value в ConcurrentDictionary. Оправдывает ли LINQ утверждение с этой точки зрения?
Спасибо за ответы.
1 ответ
Почему "словарь одновременного использования пользователями" блокируется перед выполнением какой-либо операции над этим словарем? Это необходимо?
Замок, безусловно, необходим, учитывая, как они его используют. Они выполняют несколько операций над несколькими разными словарями, и важно, чтобы ни один другой поток никоим образом не взаимодействовал ни с одним из этих словарей, пока это происходит. Для этого требуется lock
,
Единственный способ снять блокировку - это перейти к точке, где единственное использование общей структуры данных - это один вызов метода в одном параллельном словаре. Не зная точных требований, мы не можем знать, возможно ли это, но если нужны оба словаря, то, конечно, это не так.
Теперь, учитывая, что вы поставили себя в положение, когда вам всегда нужно блокировать весь доступ к параллельному словарю, нет причин использовать параллельный словарь, а не обычный словарь; вы уже приняли решение использовать собственную синхронизацию.
С моей точки зрения, оператор блокировки не нужен, потому что ConcurrentDictionary содержит поточно-ориентированные операции. Я прав?
Нет. Во-первых, к неконкурентному словарю нельзя получить доступ без блокировки.
Кроме того, я знаю о "проблеме производительности", когда вы используете операции.Count() или Key, Value в ConcurrentDictionary. Оправдывает ли LINQ утверждение с этой точки зрения?
Это ужасная идея по многим причинам. Он пытается выполнить линейный поиск по словарю, чтобы увидеть, существует ли ключ. Вы никогда не должны делать это. Вы должны использовать ContainsKey
, Кроме того, нет смысла проверять наличие ключа перед тем, как пытаться его удалить, вы можете просто попытаться удалить его и посмотреть, что произойдет. Это также совершенно небезопасно, если вы еще не блокировали, так как кто-то другой мог изменять словарь во время его итерации, и он может измениться после того, как вы его искали, делая проверку перед выполнением чего-либо бессмысленного, так как вы не можете Предположим, что то, что вы только что проверили, верно.