Используют SemaphoreSlim, Channel, concurrent-коллекции и иммутабельность вместо lock вокруг await.
Разбор
- await semaphore.WaitAsync безопасен.
- Channel для producer/consumer.
- Иногда лучше одна очередь на один потребитель.
- ConcurrentDictionary — для простых случаев.
Итог
Async-синхронизация строится на async-примитивах.