Каким будет значение переменной-счетчика после выполнения 100 корутин, каждая из которых 1000 раз увеличит её на единицу

«Каким будет значение переменной-счетчика после выполнения 100 корутин, каждая из которых 1000 раз увеличит её на единицу» — вопрос из категории Coroutines и Flow, который задают на 23% собеседований Android Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

var counter = 0
val jobs = List(100) {
    GlobalScope.launch {
        repeat(1000) { counter++ }
    }
}
runBlocking { jobs.forEach { it.join() } }
println(counter) // Результат будет меньше 100000

Без синхронизации результат будет меньше ожидаемого (100000) из-за race condition. Инкремент не атомарен - читает, изменяет и записывает значение. Для корректного результата используйте:

  1. AtomicInteger
  2. Mutex
  3. synchronized блок
  4. @Volatile + атомарные операции

Пример с AtomicInteger:

val counter = AtomicInteger(0)
// ... остальной код без изменений
println(counter.get()) // 100000