Многопоточность в C#
От потока в операционной системе до сервиса под нагрузкой
Предзаказ. Уроки выходят по мере записи и открываются без доплаты. Эта цена действует, пока идёт предзаказ. После — 14 000 ₽.
Первый раздел — 3 урока — будет открыт всем, как только выйдет: по нему видно, как устроены остальные.
Многопоточность спрашивают на четырёх собеседованиях .NET-бэкендера из пяти.
У каждого раздела ниже — как часто звучат его вопросы и сколько на них заваливают.
Один вопрос до дна
Зачёркнут ответ, после которого интервьюер кивает и идёт дальше. Рядом — тот же вопрос по четырём слоям.
- Как работает async/await?
- Метод уходит в фоновый поток и не блокирует основной
- Механика Компилятор режет метод по
awaitи собирает из кусков машину состояний. На незавершённомawaitостаток метода подписывается продолжением на ожидаемую задачу, а вызывающему уходит незавершённыйTask. - Почему так Пока база отвечает, поток не ждёт: он вернулся в пул и обслуживает другие запросы. Отдельного потока на ожидание нет.
- Как ломается Стоит где-то в цепочке появиться
.Result— и поток снова ждёт базу. Этот код выполняется в каждом запросе, и под нагрузкой так встают все потоки пула. - Как увидеть В дампе все потоки пула стоят в одном месте — в ожидании задачи. Очередь пула растёт, процессор свободен.
Для кого
Для .NET бэкенд-разработчика, которому важно не натаскаться, а разобраться. Вход — джун и мидл, выход — сеньор и выше.
Начинаем с потоков и операционной системы, а не с async. Самый частый
вопрос — как работает async/await — чаще всего заваливают те, кто отвечает
про потоки, не понимая, что такое пул и что такое Task. Поэтому async здесь
седьмой раздел, а не первый.
Примеры только серверные: ASP.NET Core, очереди, сервис под нагрузкой. Unity, WPF и UI-поток не разбираем — там те же слова значат другое.
Как устроен
Лестница снизу вверх: поток → гонка → блокировка → пул → Task → async → отмена → аллокации → сервис под нагрузкой. Каждая ступень объясняется через нижнюю: async не понять без пула, пул — без потока.
Скилл выходит в две стадии. Первая версия — 30 уроков и четыре стенда: задания в открытом репозитории, где проблему надо воспроизвести и починить. Финал — ещё 23 урока и четыре стенда: модель памяти, внутренности ThreadPool, полная диагностика, параллелизм. Купившим первую версию финал достаётся без доплаты.
Программа
14 разделов, 53 урока. Разделы идут снизу вверх — каждый объясняется через предыдущий. У раздела — его самый частый вопрос из разборов настоящих собеседований.
-
1 Карта: поток, параллельность, асинхронность В чём разница между многопоточностью, параллельностью и асинхронностью? вопросы раздела — на ~23% собеседований, заваливают 38%, раздел будет открыт всем 3 урока
- 1.1 Процесс, поток и что стоит поток бесплатно, готовится
- 1.2 Многопоточность, параллельность, асинхронность — три разных слова бесплатно, готовится
- 1.3 CPU-bound и IO-bound бесплатно, готовится
-
2 Гонки и атомарность Что такое Interlocked и зачем он нужен? вопросы раздела — на ~12% собеседований, заваливают 20% 2 урока
- 2.1 Почему ++ не атомарен готовится
- 2.2 Interlocked готовится
-
3 Блокировки Чем Mutex отличается от Semaphore и lock? вопросы раздела — на ~23% собеседований, заваливают 30% 3 урока
- 3.1 lock изнутри готовится
- 3.2 Режим пользователя, режим ядра и почему «Slim» готовится
- 3.3 Дедлок готовится
-
4 Примитивы синхронизации Какие примитивы синхронизации есть в .NET? вопросы раздела — на ~37% собеседований, заваливают 36% 4 урока
- 4.1 SemaphoreSlim готовится
- 4.2 Сигналы готовится
- 4.3 ReaderWriterLockSlim, SpinLock, SpinWait готовится
- 4.4 Карта примитивов: сценарий → инструмент готовится
-
5 ThreadPool Как работает пул потоков и как его настраивать? вопросы раздела — на ~8% собеседований 4 урока
- 5.1 Зачем пул и из чего он состоит готовится
- 5.2 Инжекция потоков и исчерпание готовится
- 5.3 Hill climbing и work stealing готовится
- 5.4 Как рантайм узнаёт, что база ответила готовится
-
6 Task В чём разница между Thread и Task? вопросы раздела — на ~20% собеседований, заваливают 29% 4 урока
- 6.1 Task — обещание, а не поток готовится
- 6.2 Исключения в Task готовится
- 6.3 Комбинаторы готовится
- 6.4 TaskCompletionSource, TaskScheduler, Task.Yield готовится
-
7 async/await: как это работает Как работает async/await? вопросы раздела — на ~65% собеседований, заваливают 27% 11 уроков
- 7.1 async — не про потоки готовится
- 7.2 Что происходит на await готовится
- 7.3 Машина состояний готовится
- 7.4 SynchronizationContext и где его нет готовится
- 7.5 ConfigureAwait(false) готовится
- 7.6 .Result и .Wait(): дедлок и его мутация готовится
- 7.7 async void, забытый await и куда деваются исключения готовится
- 7.8 Thread.Sleep против Task.Delay готовится
- 7.9 await внутри lock готовится
- 7.10 ExecutionContext, AsyncLocal, ThreadLocal готовится
- 7.11 Гигиена async готовится
-
8 Отмена Зачем нужен CancellationToken и как отменить задачу? вопросы раздела — на ~9% собеседований 2 урока
- 8.1 Кооперативная отмена готовится
- 8.2 Связывание, таймауты, ASP.NET Core готовится
-
9 ValueTask и аллокации Чем ValueTask отличается от Task и когда что брать? вопросы раздела — на ~8% собеседований, заваливают 33% 2 урока
- 9.1 Task против ValueTask готовится
- 9.2 IValueTaskSource и пул машин состояний готовится
-
10 Почему сервис встал Что такое thread starvation? 6 уроков
- 10.1 Starvation на стенде готовится
- 10.2 Первые метрики готовится
- 10.3 Дамп живого процесса готовится
- 10.4 Трейсы готовится
- 10.5 Дерево диагностики готовится
- 10.6 Сервис под нагрузкой: всё вместе готовится
-
11 Коллекции и очереди Как устроен ConcurrentDictionary? 4 урока
- 11.1 Потокобезопасные коллекции готовится
- 11.2 Producer-consumer: BlockingCollection готовится
- 11.3 Channel<T> готовится
- 11.4 IAsyncEnumerable готовится
-
12 Модель памяти и lock-free Что такое volatile и когда он нужен? 4 урока
- 12.1 Кэши, переупорядочивание, видимость готовится
- 12.2 volatile и барьеры готовится
- 12.3 Lock-free и CAS готовится
- 12.4 Неизменяемость как стратегия готовится
-
13 Параллелизм Сколько потоков используют Parallel.For и Parallel.ForEachAsync? 3 урока
- 13.1 Parallel.For, ForEach, ForEachAsync готовится
- 13.2 PLINQ готовится
- 13.3 TPL Dataflow готовится
-
14 Async в тестах 1 урок
- 14.1 Как тестировать асинхронный и многопоточный код готовится
Предзаказ. Уроки выходят по мере записи и открываются без доплаты. Эта цена действует, пока идёт предзаказ. После — 14 000 ₽.
- Доступ на год, продление бесплатное — кнопкой в кабинете. Ссылка для входа приходит на почту, пароль не нужен.
- Семь дней на возврат без объяснения причин — с того дня, как тебе открылся первый урок. Тоже кнопкой в кабинете, писать никому не надо.