코루틴은 동시성 작업을 다루는 데 유용한 도구이며, 동시에 여러 코루틴이 접근하는 공유 데이터에 대한 동기화를 효과적으로 처리할 수 있습니다.
1. Mutex (Mutual Exclusion)
코루틴 간에 공유된 데이터에 안전하게 접근하기 위해 Mutex를 사용할 수 있습니다.
Mutex는 임계 영역(Critical Section)을 설정하여 한 번에 하나의 코루틴만 해당 영역에 접근할 수 있게 합니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
var sharedVariable = 0
val mutex = Mutex()
suspend fun increment() {
mutex.withLock {
// 여기서의 코드는 오직 한 코루틴만 실행됩니다.
sharedVariable++
}
}
fun main() = runBlocking {
val job = launch {
repeat(1000) {
increment()
}
}
val job2 = launch {
repeat(1000) {
increment()
}
}
job.join()
job2.join()
println("Result: $sharedVariable") // Result: 2000
}
2. CoroutineContext를 공유
CoroutineContext를 공유하여 코루틴 간에 공유 데이터에 안전하게 접근할 수 있습니다.
이 방법은 코루틴이 실행되는 환경을 공유함으로써 동기화를 달성합니다.
import kotlinx.coroutines.*
val sharedContext = newSingleThreadContext("sharedContext")
suspend fun safeUpdateSharedData() = withContext(sharedContext) {
// 공유 데이터 업데이트
}
3. Actor 패턴
Actor는 코루틴 간에 메시지를 보내고 받는 메커니즘을 제공합니다.
Actor를 사용하면 메시지 처리가 순차적으로 이루어지므로 공유 상태에 대한 동기화를 신경 쓸 필요가 없습니다.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.actor
sealed class Message
data class UpdateData(val data: Int) : Message()
val actor = GlobalScope.actor<Message> {
var sharedData = 0
for (msg in channel) {
when (msg) {
is UpdateData -> sharedData += msg.data
}
}
}
// 사용
runBlocking {
actor.send(UpdateData(42))
}
4. Atomic 변수 사용
Atomic 타입은 원자성을 보장하여 여러 스레드나 코루틴에서 안전하게 값을 읽고 쓸 수 있도록 도와줍니다.
import kotlinx.coroutines.*
import java.util.concurrent.atomic.AtomicInteger
val atomicVariable = AtomicInteger(0)
suspend fun increment() {
atomicVariable.incrementAndGet()
}
fun main() = runBlocking {
val job = launch {
repeat(1000) {
increment()
}
}
val job2 = launch {
repeat(1000) {
increment()
}
}
job.join()
job2.join()
println("Result: ${atomicVariable.get()}") // Result: 2000
}
'Kotlin > 비동기 프로그래밍' 카테고리의 다른 글
[Kotlin] 스레드간 동기화 방법 (0) | 2023.11.22 |
---|