Исходный код вики ConcurrentDictionary
Версия 11.1 от Alexandr Fokin на 2022/01/03 15:31
Скрыть последних авторов
author | version | line-number | content |
---|---|---|---|
![]() |
11.1 | 1 | |
![]() |
1.1 | 2 | |
![]() |
11.1 | 3 | **Описание работы метода AddOrUpdate**: |
4 | В dictionary есть одно значение по ключу key1 - val1. | ||
![]() |
1.1 | 5 | |
![]() |
11.1 | 6 | 1) Поток th1 запускает Update делегат по ключу key1. (Фиксирует текущее значение th1_v) |
7 | 2) Поток th2 запускает Update делегат по ключу key1. (Фиксирует текущее значение th2_v) | ||
8 | 3) Поток th2 заканчивает выполнение делегата Update. th1 сравнивает val1 = th2_v (Через equils). | ||
9 | Значение равны и th2 сохраняет результат. | ||
10 | 4) Поток th1 заканчивает выполнение делегата Update. th2 сравнивает val1 = th1_v (Через equils). | ||
11 | Значение НЕ равны и th2 повторно вызывает Update делегат. | ||
12 | (Если элемент был удален, то запустить делегат Add) | ||
13 | !Повторного вызова делегата не произойдет, в случает если результат работы th2 эквивалентен исходному начальному значению val1. | ||
![]() |
1.1 | 14 | |
![]() |
11.1 | 15 | Получается, что ни вызов AddOrUpdate, ни вызов конкретного делегата (Add/Update) сам по себе не блокирует значение в коллекции и не препятствует в изменении другими потокам. |
![]() |
1.1 | 16 | |
![]() |
11.1 | 17 | По сути мы получаем **оптимистичную блокировку**. В случае неудачи которой, повторно вызывается действие обработки (add/update) для измененного значения по указанному ключу. |
18 | Критерием сравнения блокировки является Equils. В таком случае возможно имеет смысл перегрузка Equils и наличии в сущности некоторого ключевого поля. Нечто вроде Change Version TimeStamp. |