
От потоков к корутинам: как и почему видоизменились примитивы синхронизации в языке Kotlin (Часть 2)
Aprsta 16 минут назад От потоков к корутинам: как и почему видоизменились примитивы синхронизации в языке Kotlin (Часть 2) Средний 15 мин 780 Блог компании Garage Eight Программирование * Android * Параллельное...
Anthropic — What company has the best second artificial intelligence model at the end of June?
В сфере искусственного интеллекта произошло заметное событие. Aprsta 16 минут назад От потоков к корутинам: как и почему видоизменились примитивы синхронизации в языке Kotlin (Часть 2) Средний 15 мин 780 Блог компании Garage Eight Программирование * Android * Параллельное программирование * Kotlin * Обзор В первой части статьи были рассмотрены следующие распространённые способы организации конкурентного кода при работе с потоками и корутинами: критические секции, атомарные переменные, реактивные переменные, барьерная синхронизация. В этой части будут разобраны другие важные подходы:Ограничение параллелизма:Семафоры. Синхронизированный обмен данными:Каналы передачи данных.
Thread confinement:Модель акторов. Последовательные обработчики задач. Dispatcher confinement.
Технические детали
Для каждого из этих подходов рассмотрим конкретные реализации, выделим плюсы и минусы, приведём примеры использования. В конце объединим все реализации в общую таблицу. Ограничение параллелизмаВ первой части статьи уже были описаны критические секции, которые ограничивают участок кода и не позволяют выполнять его одновременно более чем одному потоку или корутине.
В этом разделе рассмотрим менее строгий ограничитель параллелизма — семафоры. СемафорыСемафоры ограничивают количество потоков (или корутин), которые могут получить одновременный доступ к выбранному участку кода. В стандартной библиотеке корутин уже есть реализация семафора — kotlinx.
Если не вдаваться в детали, то корутинная реализация семафора не будет принципиально отличаться от java. Semaphore, за исключением очевидного — в kotlinx. Semaphore ограничивается количество корутин, а не количество потоков.
Отраслевые последствия
Ограничение в виде количества корутин задаётся в конструкторе (параметр permits). Пример использования семафоров в условиях параллелизма и ограниченной памяти:val systemMemory = AtomicInteger(1_024) fun main() = runBlocking { val coroutinesCount = 5 val semaphore = Semaphore(coroutinesCount) Array(1_000) { async(Dispatchers. IO) { semaphore } } println("Success!
}В данном коде память строго ограничена — systemMemory равна 1024. Есть задача emulateHeavyTask, которая требует ровно 200 единиц памяти. И если ее одновременно запустит больше пяти корутин, то сработает проверка assertTrue(«Not enough memory for task!
Здесь семафор дает возможность обрабатывать задачи группами — не больше пяти корутин одновременно, что позволяет эффективно распределять ограниченные ресурсы. Вот несколько типичных задач, для которых могут понадобиться семафоры: Ограничение количества одновременных запросов к серверу. Помимо оптимизации, мы не превысим rate limit сервера.
Этот прогресс даёт важные сигналы о будущем отрасли, и технологический мир внимательно наблюдает.





