📌 Kotlin Coroutines의 CopyableThreadContextElement
이해하기
1. 개요
CopyableThreadContextElement
는 ThreadContextElement
를 확장한 인터페이스로, 자식 코루틴이 해당 컨텍스트를 상속할 때마다 복사됩니다. 이는 ThreadLocal
을 사용하는 API에서 코루틴이 "코루틴 안전"하게 ThreadLocal
에 쓰기 작업을 수행할 수 있도록 합니다.
2. 주요 기능
- 코루틴별 쓰기 격리: 코루틴이
CopyableThreadContextElement
를 통해ThreadLocal
에 쓰기를 수행하면, 해당 코루틴과 이후에 시작된 자식 코루틴에서만 그 값을 볼 수 있습니다. 부모 코루틴, 동료 코루틴, 또는 동일한 스레드를 사용하는 다른 코루틴에서는 이 값을 볼 수 없습니다. - 구조적 동시성 지원: 코루틴이 구조적 동시성을 유지하면서도 가변적인
ThreadLocal
API를 투명하고 올바르게 사용할 수 있도록 합니다.
3. 사용 예시
다음은 메서드 추적을 위해 ThreadLocal
을 "코루틴 로컬"로 변환하는 예시입니다:
class TraceContextElement(private val traceData: TraceData?) : CopyableThreadContextElement<TraceData?> {
companion object Key : CoroutineContext.Key
override val key: CoroutineContext.Key = Key
override fun updateThreadContext(context: CoroutineContext): TraceData? {
val oldState = traceThreadLocal.get()
traceThreadLocal.set(traceData)
return oldState
}
override fun restoreThreadContext(context: CoroutineContext, oldState: TraceData?) {
traceThreadLocal.set(oldState)
}
override fun copyForChild(): TraceContextElement {
// 자식 코루틴이 시작될 때 ThreadLocal의 현재 값을 복사합니다.
return TraceContextElement(traceThreadLocal.get()?.copy())
}
override fun mergeForChild(overwritingElement: CoroutineContext.Element): CoroutineContext {
// 병합 작업은 부모 코루틴과 자식 코루틴 모두에 동일한 키를 가진 요소가 있을 때 처리 방법을 정의합니다.
return TraceContextElement(traceThreadLocal.get()?.copy())
}
}
위의 예시에서, 코루틴은 이 메커니즘을 사용하여 해당 스레드 로컬 요소의 값이 대상 스레드 로컬에 설치되었다고 가정하는 Java 코드를 안전하게 호출할 수 있습니다.
4. 재진입성과 스레드 안전성
이 인터페이스의 올바른 구현은 restoreThreadContext
호출이 이후의 updateThreadContext
및 restoreThreadContext
작업과 병렬로 발생할 수 있음을 예상해야 합니다. 따라서 모든 CopyableThreadContextElement
의 구현은 스레드 안전해야 하며, 요소 내의 내부 가변 상태를 적절히 보호해야 합니다.
📌 원본 출처
본 문서의 내용은 Kotlin 공식 문서를 참고하여 작성되었습니다. 자세한 내용은 아래 공식 문서를 통해 확인할 수 있습니다.
'Kotlin > kotlinx.coroutines' 카테고리의 다른 글
CoroutineDispatcher (0) | 2025.02.07 |
---|---|
CopyableThrowable (0) | 2025.02.07 |
CompletionHandler (0) | 2025.02.07 |
completeWith (0) | 2025.02.07 |
CompletableJob (0) | 2025.02.07 |