Я следил за курсом Pluralsight, автором которого является Саймон Робинсон в Concurrent Collections.
Он использует AddOrUpdate
следующим образом, чтобы сделать его потокобезопасным:
public bool TrySellShirt(string code)
{
bool success = false;
_stock.AddOrUpdate(code,
(itemname) => { success = false; return 0; },
(itemName, oldValue) =>
{
if (oldValue == 0)
{
success = false;
return 0;
}
else
{
success = true;
return oldValue - 1;
}
});
if (success)
Interlocked.Increment(ref _totalQuantitySold);
return success;
}
Итак, я знаю, что AddOrUpdate не является полностью атомарным, как сказано в документации: делегаты addValueFactory и updateValueFactory вызываются вне блокировок, чтобы избежать проблем, которые могут возникнуть при выполнении неизвестного кода под блокировкой.< /эм>
Это мне понятно. Что не ясно, так это какой смысл устанавливать success
в false
в делегатах. Аргумент AddValueFactory
намеренно используется как лямбда, поэтому можно установить success = false
, а не просто возвращать 0. Я немного понимаю/думаю, что если метод/лямбда прерывается другим потоком (и он может быть прерван, потому что он вызывается вне блокировки), он попытается повториться, поэтому мы должны установить состояние любых соответствующих значений на их начальное значение, чтобы четко включить новую итерацию, поэтому установите success = false;
.
Также из документации: Если вы вызываете AddOrUpdate одновременно в разных потоках, addValueFactory может вызываться несколько раз, но его пара ключ/значение может не добавляться в словарь при каждом вызове.
Если это так, я проверял исходный код AddOrUpdate
на source.dot.net, я не вижу нигде используемых блокировок, я вижу TryAddInternal
и TryUpdateInternal
.
Тем не менее, описанный выше метод работает, но я не понимаю, почему он работает, и как только я удаляю, казалось бы, ненужные success = false
назначения, он не работает, возникает несоответствие. Так что мне любопытно, что заставляет этих делегатов повторяться после неудачи?
У меня есть вопросы:
1. Безопасно ли использовать AddOrUpdate
, как показано, или я должен просто заблокировать все и забыть об этом?
2. Что заставляет делегатов повторяться после того, как их прервали? Имеет ли это какое-либо отношение к «Сравнить и поменять местами»? (самое интересное в этом);
3. Есть ли какие-либо темы/концепции, которые вы хотели бы, чтобы я проверил, чтобы лучше понять потокобезопасную среду?