Synchronized

GPT:

In Kotlin, you can use the synchronized block to ensure that a particular section of your code is executed by only one thread at a time, similar to Java. This is particularly useful when you are dealing with shared resources or concurrent execution of code. Below is a simple example to demonstrate how you can use synchronized in Kotlin.

Firstly, define a shared resource. For simplicity, let's consider a shared counter:

class Counter {
    var count = 0

    fun increment() {
        synchronized(this) {
            count++
        }
    }
}

In this example:

  1. Shared Resource: count is a shared resource among threads.
  2. Method: increment() is a method that increments the counter.
  3. Synchronized Block: synchronized(this) { ... } ensures that the code block inside is executed by only one thread at a time. The this refers to the current instance of the class, meaning the lock is on the instance of the Counter class.

When a thread enters a synchronized block, it acquires the intrinsic lock (monitor lock) of the specified object (this in this case). No other thread can enter any synchronized block on the same object until the lock is released by the first thread.

To use this Counter class:

fun main() {
    val counter = Counter()

    // Creating 1000 threads that increment the counter
    val threads = List(1000) {
        Thread {
            counter.increment()
        }
    }

    // Start all threads
    threads.forEach { it.start() }

    // Wait for all threads to finish
    threads.forEach { it.join() }

    println(counter.count)
}

In this main function:

  • Threads Creation: We create 1000 threads, each of which calls counter.increment().
  • Starting Threads: All threads are started with it.start().
  • Waiting for Completion: it.join() is used to wait for the completion of each thread.

By synchronizing the increment operation, even when multiple threads are accessing and modifying the count, the synchronized block ensures that the operation is thread-safe, preventing concurrent modification anomalies.

Remember that synchronization comes with a cost in terms of performance due to the overhead of acquiring and releasing locks. Use it judiciously, only around the critical section of your code where thread safety is a concern.