[kotlin] 코틀린에서의 스레드 로컬 변수 활용 방법

코틀린은 자바와 마찬가지로 멀티스레드 환경에서 안전한 프로그래밍을 위해 스레드 로컬 변수(Thread-Local Variables)를 제공합니다. 스레드 로컬 변수는 각 스레드별로 독립적인 값을 가지며, 스레드 간에 공유되지 않습니다. 이를 통해 각 스레드에서 자신만의 상태를 유지하고 접근할 수 있습니다.

코틀린에서 스레드 로컬 변수를 활용하는 방법은 다음과 같습니다.

1. ThreadLocal 클래스 활용

가장 기본적인 방법은 ThreadLocal 클래스를 사용하는 것입니다. 이 클래스는 제네릭으로 선언되어 특정 타입에 대한 스레드 로컬 변수를 생성할 수 있습니다. 아래는 ThreadLocal을 활용하여 스레드 로컬 변수를 생성하는 예제 코드입니다.

import java.util.concurrent.atomic.AtomicInteger

class MyThreadLocal {
    private val threadId = AtomicInteger(0)
    
    private val threadLocal = ThreadLocal<Int>()

    fun nextThreadId(): Int {
        threadLocal.set(threadId.incrementAndGet())
        return threadLocal.get()
    }
}

fun main() {
    val myThreadLocal = MyThreadLocal()

    val thread1 = Thread { 
        println("Thread 1 id: ${myThreadLocal.nextThreadId()}")
        Thread.sleep(1000)
        println("Thread 1 id: ${myThreadLocal.nextThreadId()}")
    }
    
    val thread2 = Thread {
        println("Thread 2 id: ${myThreadLocal.nextThreadId()}")
        Thread.sleep(1000)
        println("Thread 2 id: ${myThreadLocal.nextThreadId()}")
    }

    thread1.start()
    thread2.start()

    thread1.join()
    thread2.join()
}

위 예제 코드에서 MyThreadLocal 클래스는 ThreadLocal을 활용하여 스레드별로 고유한 ID를 생성하는 nextThreadId() 메서드를 제공합니다. 두 개의 스레드가 nextThreadId()를 호출하면 각각 다른 ID를 받아올 수 있습니다.

2. 코루틴을 활용한 스레드 로컬 변수

코틀린의 코루틴을 활용하면 스레드 로컬 변수를 더욱 효율적으로 활용할 수 있습니다. 코루틴은 비동기적인 동작을 동시성으로 처리하는 데 사용되는 경량 스레드입니다. 아래는 코루틴을 활용하여 스레드 로컬 변수를 사용하는 예제 코드입니다.

import kotlinx.coroutines.*

val threadLocal = ThreadLocal<Int>()

fun main() = runBlocking {
    val job1 = launch(Dispatchers.Default) {
        threadLocal.set(1)
        println("Thread 1: ${threadLocal.get()}")
        delay(1000)
        println("Thread 1: ${threadLocal.get()}")
    }
    
    val job2 = launch(Dispatchers.Default) {
        threadLocal.set(2)
        println("Thread 2: ${threadLocal.get()}")
        delay(1000)
        println("Thread 2: ${threadLocal.get()}")
    }

    job1.join()
    job2.join()
}

위 예제 코드에서 threadLocal 변수는 공유 변수로 사용됩니다. 각 코루틴은 threadLocal 변수에 독립적인 값을 설정하고 읽어올 수 있습니다. 이를 통해 각 코루틴에서는 자신만의 로컬 상태를 유지할 수 있습니다.

참고 자료