Synchronized

Synchronized является ключевым механизмом синхронизации в Java и Kotlin, предназначенным для обеспечения потокобезопасности при доступе к общим данным из нескольких потоков. Ключевое слово synchronized можно использовать для создания критических секций, которые гарантируют, что только один поток может выполнять код внутри синхронизированного блока одновременно.

Есть два способа синхронизации - метода и блока.

Неправильный пример

class Counter {
    private var count = 0

    fun increment() {
        count++
    }

    fun getCount(): Int {
        return count
    }
}

fun main() {
    val counter = Counter()

    val thread1 = thread {
        repeat(1000) {
            counter.increment()
        }
    }

    val thread2 = thread {
        repeat(1000) {
            counter.increment()
        }
    }

    thread1.join()
    thread2.join()

    println("Counter value: ${counter.getCount()}") 
    // Ожидаемое значение: 2000
    ==>  Counter value: 1987
}

В этом примере несоответствие ожидаемого результата с практическим произошло из-за состояния гонки данных: операция инкремента не является атомарное и два потока могут одновременно прочитать одно и то же значение и записать его.

Исправленный пример

class Counter {
    private var count = 0

    @Synchronized
    fun increment() {
        count++
    }

    @Synchronized
    fun getCount(): Int {
        return count
    }
}

fun main() {
    val counter = Counter()

    val thread1 = thread {
        repeat(1000) {
            counter.increment()
        }
    }

    val thread2 = thread {
        repeat(1000) {
            counter.increment()
        }
    }

    thread1.join()
    thread2.join()

    println("Counter value: ${counter.getCount()}") // Ожидаемое значение: 2000
}

Потенциальные проблемы: Отсутствуют. В данном случае использование аннотации @Synchronized над методами increment() и getCount() гарантирует, что только один поток может одновременно выполнять код внутри этих методов, что исключает состояние гонки.