Я получил некоторую скорбь об этом в комментарии, который я опубликовал на днях, поэтому я хотел опубликовать вопрос в попытке, чтобы люди сказали мне, что я сумасшедший, что я приму, или скажите мне, что яможет быть и прав, что я тоже с удовольствием приму.Я также могу принять что-нибудь между ними.
Допустим, у вас есть необезопасный тип объекта, такой как Dictionary<int, string>
.В качестве аргумента я знаю, что вы также можете использовать ConcurrentDictionary<int, string>
, который является поточно-ориентированным, но я хочу поговорить об общих принципах, касающихся не поточно-ориентированных объектов в многопоточной среде.
Рассмотримследующий пример:
private static readonly Dictionary<int, string> SomeDictionary = new Dictionary<int, string>();
private static readonly object LockObj = new object();
public static string GetById(int id)
{
string result;
/** Lock Bypass **/
if (SomeDictionary.TryGetValue(id, out result)
{
return result;
}
lock (LockObj)
{
if (SomeDictionary.TryGetValue(id, out result)
{
return result;
}
SomeDictionary.Add(id, result = GetSomeString());
}
return result;
}
Шаблон блокировки называется Блокировка с двойной проверкой , поскольку блокировка активно обходится, если словарь уже инициализирован с этим идентификатором.Метод «Добавить» словаря вызывается внутри блокировки, потому что мы хотим вызвать метод только один раз, потому что он вызовет исключение, если вы попытаетесь добавить элемент с тем же ключом.
Это был мойпонимание того, что этот шаблон блокировки по существу синхронизирует способ обработки словаря, что позволяет ему быть поточно-ориентированным.Но я получил несколько негативных комментариев о том, что это не делает его потокобезопасным.
Итак, мой вопрос: приемлем ли этот шаблон блокировки для не поточно-безопасных объектов в многопоточной среде?Если нет, то какой шаблон лучше использовать?(при условии, что нет идентичного типа C #, который является потокобезопасным)