Новое:Talanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

+1 164новые вакансии за сутки·93 595вакансий открыто сейчас·Новое:Talanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

Новые вакансии в TelegramРаботодателям
Talanto
Вакансии
Компании7 266
РезюмеAIПодготовкаСтатьи
BoostТарифыBoost
Войти

Не нашли подходящее?

Пусть нужная вакансия найдёт вас сама.

  1. Подборка в TelegramНовые вакансии по вашему фильтру — сразу в бота.Подключить
  2. Мэтчи по резюмеЗагрузите резюме — покажем, где вы подходите лучше всего.Загрузить
  3. Сохранить фильтрНастройте поиск один раз и возвращайтесь к новым вакансиям.Настроить
Что нового на TalantoTalanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

Для работодателей

Опубликуйте вакансию — отклики придут в ваш кабинет.

  1. Вакансиябесплатно
  2. Откликиконтакты бесплатно
  3. Наймэтапы и интервью

40 компаний публикуют вакансии напрямую · 4 401 кандидат открыт к предложениям

Разместить вакансию

Популярные направления

Все подборки
  • Python17 121
  • Облачные технологии14 079
  • QA вакансии3 451
  • Backend вакансии2 115
  • Инженер данных1 805
  • Продакт-менеджер1 260

Разработка

  • Android1 862
  • iOS1 700
  • Fullstack вакансии986
  • AI вакансии950
  • Frontend вакансии744
  • Mobile вакансии44

По стеку

  • Go8 659
  • Java6 537
  • Node.js2 020
  • .NET1 721
  • Kotlin1 614
  • Rust1 455
  • C#710
  • PHP681
  • C++571

DevOps и инфраструктура

  • Kubernetes7 772
  • DevOps вакансии6 050
  • Linux-инфраструктура5 488
  • Terraform / IaC4 272
  • CI/CD3 239
  • Мониторинг и Observability1 789
  • SRE567
  • Кибербезопасность452

Аналитика и данные

  • Data Scientist1 140
  • Бизнес-аналитик923
  • Аналитик данных855
  • Системный аналитик152

Другие направления

  • Проджект-менеджер615
  • UI/UX дизайн146
  • Ручное тестирование14

По регионам

  • Вакансии в США44 276
  • Вакансии в Европе23 819
  • Вакансии в Канаде4 471
  • Работа в России3 904

По формату

  • Удалённые вакансии74 928
  • Релокация в США44 273
  • Гибридная работа12 388
  • Офисная работа7 083

По уровню

  • Senior вакансии42 627
  • Middle вакансии20 864
  • Junior вакансии6 721

Сейчас нанимают

Все компании
  • Wise190 вакансий
  • Rakuten189 вакансий
  • ASML166 вакансий
  • Grab137 вакансий
  • Celonis39 вакансий
  • Spotify37 вакансий
  • Adyen28 вакансий
  • Infobip28 вакансий
  • Monzo20 вакансий
  • Darktrace16 вакансий

Вакансии из 344 источников: карьерные страницы компаний и джоб-борды.

КомпанииО насНовостиПубличная офертаУсловия использованияПолитика конфиденциальностиПоддержка
←К теме Kotlin CoroutinesВсе вопросы
Kotlin CoroutinesMiddleТеория

Что такое Mutex в coroutines и когда его использовать для защиты разделяемого состояния?

В закладки
Сначала попробуйте ответить сами30 секунд
Сравнить с ответом ↓

Mutex из kotlinx.coroutines.sync — корутин-осознанный замок: lock() приостанавливает корутину без блокировки потока. Используйте withLock { } для защиты разделяемого изменяемого состояния. Mutex не реентерабелен — повторный захват из той же корутины приведёт к дедлоку.

Проблема: состояние гонки

import kotlinx.coroutines.*

var counter = 0

fun main() = runBlocking {
    val jobs = List(1000) {
        launch(Dispatchers.Default) {
            counter++  // НЕ атомарно — data race!
        }
    }
    jobs.forEach { it.join() }
    println(counter)  // результат непредсказуем, не 1000
}

Mutex в Kotlin Coroutines

Mutex (mutual exclusion lock) из пакета kotlinx.coroutines.sync — это корутин-осознанный взаимоисключающий замок. В отличие от java.util.concurrent.locks.ReentrantLock, Mutex.lock() — это suspend-функция: ожидающая корутина приостанавливается, не блокируя поток.

Решение с Mutex

import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock

val mutex = Mutex()
var counter = 0

fun main() = runBlocking {
    val jobs = List(1000) {
        launch(Dispatchers.Default) {
            mutex.withLock {  // suspend, не блокирует поток
                counter++
            }
        }
    }
    jobs.forEach { it.join() }
    println(counter)  // всегда 1000
}

withLock — extension-функция, которая вызывает lock(), выполняет блок и вызывает unlock() в finally, гарантируя освобождение замка даже при исключении.

Низкоуровневый API

val mutex = Mutex()

// Явный lock/unlock
mutex.lock(owner = this)   // suspend
try {
    // критическая секция
} finally {
    mutex.unlock(owner = this)
}

// Неблокирующая попытка захватить замок
if (mutex.tryLock()) {
    try { /* ... */ } finally { mutex.unlock() }
} else {
    // замок занят, делаем что-то другое
}

Когда использовать Mutex

  • Защита изменяемого состояния, доступного из нескольких корутин параллельно.
  • Кэш с ленивой инициализацией, где несколько корутин могут одновременно промахнуться по кэшу.
  • Ограничение параллельного доступа к ресурсу (например, файлу или стороннему SDK).

Альтернативы

  • AtomicInteger / AtomicReference — для примитивных атомарных операций без suspend.
  • Single-threaded dispatcher: Dispatchers.IO.limitedParallelism(1) — состояние меняется только в одном потоке.
  • Actor (obsolete): actor { } устарел в пользу Channel + корутина-обработчик.
  • Channel / StateFlow: для реактивного обновления состояния вместо прямого мутирования.
// Альтернатива: конфайн состояние в один поток
val singleThread = Dispatchers.IO.limitedParallelism(1)
var counter = 0

launch(singleThread) {
    repeat(1000) { counter++ }  // безопасно — один поток
}

Подводные камни

  • Mutex не реентерабелен: если корутина, владеющая замком, попытается захватить его снова — дедлок. В отличие от ReentrantLock, Mutex не поддерживает повторный вход.
  • Не вызывайте suspend внутри lock без withLock: если suspend-функция бросит исключение, а unlock не завершится — замок никогда не освободится. Всегда используйте withLock или try/finally.
  • Мьютекс и отмена: если корутина отменяется, находясь в очереди на lock(), она получает CancellationException и не захватывает замок. Если она уже внутри критической секции — unlock вызывается через finally.
  • Производительность: при высокой конкуренции Mutex создаёт серьёзное bottleneck. Рассмотрите lock-free структуры данных или разбивку состояния.
  • Deadlock при вложенных Mutex: если корутина A держит mutex1 и ждёт mutex2, а корутина B держит mutex2 и ждёт mutex1 — дедлок.
  • withLock не защищает само поле: объявив поле volatile или lateinit, вы не получаете защиты от гонки — нужен именно Mutex вокруг чтения И записи.

Типичные ошибки

  • Объяснять «Mutex в coroutines» только как синтаксис и не описывать поведение runtime/compiler.
  • Игнорировать важный риск: Держать Mutex вокруг долгого I/O или вызывать внешний callback внутри lock опасно для latency и deadlocks.
  • Давать пример без edge case: отмены, null, recomposition, platform boundary или ошибки.

Что проверяет интервьюер

  • Формулирует суть темы «Mutex в coroutines» своими словами и связывает ее с кодом.
  • Называет механизм: withLock suspend-ится, пока lock недоступен, и освобождает lock при выходе из блока.
  • Видит production-последствие: Держать Mutex вокруг долгого I/O или вызывать внешний callback внутри lock опасно для latency и deadlocks.

Как вы знаете этот вопрос?

Проверить себя по теме Kotlin Coroutines →

Источники

  • https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.sync/-mutex/
  • https://kotlinlang.org/docs/shared-mutable-state-and-concurrency.html

Связанные темы

Kotlin Coroutinesconcurrencykotlin coroutinesmutex-shared-state-reasoning

Частые вопросы на собеседовании

  • Что такое structured concurrency и почему это важно?
  • В чём разница между билдерами coroutine launch и async?
  • Что такое suspend-функция и где её можно вызывать?
  • Что такое Flow в Kotlin и чем он отличается от suspend fun, возвращающей одно значение?