Українська
Підсумки
Висновки
Звичайні колекції .NET не розраховані на одночасні записи: вони гублять дані, генерують винятки або зависають, а складені операції «перевірити – діяти» небезпечні навіть для потокобезпечних колекцій. Конкурентні колекції System.Collections.Concurrent пропонують атомарні методи Try…, GetOrAdd і AddOrUpdate; частина з них побудована на неблокуючих алгоритмах з операцією CAS, як стек Трейбера. Фабрики словника виконуються поза блокуванням, тому дорогі обчислення загортають у Lazy<T>. Незмінні та заморожені колекції дозволяють читати без блокувань, а оновлювати – атомарною заміною посилання. Патерн «виробник – споживач» реалізують через BlockingCollection<T> для потоків або канали для асинхронного коду; обмежена ємність дає зворотний тиск, а сигнал завершення – коректну зупинку конвеєра. Хибне розділення кешу знищує масштабованість, коли потоки записують сусідні змінні однієї кеш-лінії; його усувають локальними змінними й доповненням структур і виявляють вимірюваннями, профілювальником dotTrace та perf c2c.
Питання для самоперевірки
- Чому
List<T>іDictionary<TKey, TValue>не можна змінювати з кількох потоків? - Що таке складена операція «перевірити – діяти»? Як її виправити?
- Що виконує
Interlocked.CompareExchange? Що таке неблокуючий алгоритм? - Як працює стек Трейбера?
- У чому полягає проблема ABA і чому в .NET вона менш гостра?
- Чим відрізняються
ConcurrentQueue<T>,ConcurrentStack<T>іConcurrentBag<T>? - Коли
ConcurrentBag<T>ефективний, а коли ні? - Чому фабрика
GetOrAddможе виконатися кілька разів? Як цьому запобігти? - Якою має бути функція оновлення в
AddOrUpdate? - Як незмінні колекції дозволяють читати без блокувань? Для чого
ImmutableInterlocked? - Для яких сценаріїв призначено
FrozenDictionary<TKey, TValue>? - Які можливості додає
BlockingCollection<T>? Як завершити роботу споживачів? - Що таке зворотний тиск? Порівняйте сигнал завершення й «отруйну пігулку».
- Які режими переповнення має обмежений канал? Чим канал відрізняється від
BlockingCollection<T>? - Що таке кеш-лінія та хибне розділення? Як його виявити й усунути?
Корисні посилання
- Потокобезпечні колекції: https://learn.microsoft.com/dotnet/standard/collections/thread-safe/
BlockingCollection<T>: https://learn.microsoft.com/dotnet/standard/collections/thread-safe/blockingcollection-overviewConcurrentDictionary<TKey, TValue>: https://learn.microsoft.com/dotnet/api/system.collections.concurrent.concurrentdictionary-2- Канали: https://learn.microsoft.com/dotnet/core/extensions/channels
- Незмінні колекції: https://learn.microsoft.com/dotnet/api/system.collections.immutable
FrozenDictionary<TKey, TValue>: https://learn.microsoft.com/dotnet/api/system.collections.frozen.frozendictionary-2- BenchmarkDotNet: https://benchmarkdotnet.org/
- Профілювання в Rider: https://www.jetbrains.com/help/rider/Profiling_Applications.html
perf c2c: https://man7.org/linux/man-pages/man1/perf-c2c.1.html