Java/Kotlin

[Coroutine] 코루틴 학습 - 13 (Actors)

Icarus8050 2022. 5. 17. 14:22
반응형

Actor

  • 컴퓨터 과학에서 Actor model은 Actor를 병렬 컴퓨팅의 보편적인 기본 요소로 취급하는 수학적 모델이다.
  • 액터는 메시지에 대한 응답으로 지역적인 결정을 내리고, 더 많은 액터를 생성하고, 메시지를 전송하고, 수신된 다음 메시지에 응답하는 방법을 결정할 수 있다.
  • 액터는 자신의 비공개 상태를 수정할 수 있지만 메시징을 통해 간접적으로만 서로에게 영향을 줄 수 있다. (이는 잠금 기반의 동기화 필요성을 없앤다.)
  • 각각의 액터는 싱글 쓰레드로 동작하고 메시지를 차례로 처리한다.

 

 코루틴에서는 액터를 꽤나 쉽게 구현할 수 있다.

 아래의 예시는 동기화 문제가 발생하지 않는다. 액터가 싱글쓰레드로 동작하고 있기 때문이다. 액터 모델을 간단하게 만들기 위해서는 코루틴 빌더를 이용하면 된다. 

sealed class CounterMsg
object IncCounter : CounterMsg()
class GetCounter(
    val response: CompletableDeferred<Int>
) : CounterMsg()

fun CoroutineScope.counterActor(): Channel<CounterMsg> {
    val channel = Channel<CounterMsg>()
    launch {
        var counter = 0
        for (msg in channel) {
            when (msg) {
                is IncCounter -> {
                    counter++
                }
                is GetCounter -> {
                    msg.response.complete(counter)
                }
            }
        }
    }
    return channel
}

suspend fun CoroutineScope.massiveRun(action: suspend () -> Unit) {
    val n = 100
    val k = 1000
    val time = measureTimeMillis {
        val jobs = List(n) {
            launch {
                repeat(k) {
                    action()
                }
            }
        }
        jobs.forEach { it.join() }
    }
    println("Completed ${n * k} actions in $time ms")
}

suspend fun main(): Unit = coroutineScope {
    val counter: SendChannel<CounterMsg> = counterActor()
    massiveRun { counter.send(IncCounter) }
    val response = CompletableDeferred<Int>()
    counter.send(GetCounter(response))
    println(response.await())
    counter.close()
}

 


참고자료

https://www.amazon.com/Kotlin-Coroutines-Deep-Marcin-Moskala/dp/8396395837

https://kotlinlang.org/docs/shared-mutable-state-and-concurrency.html#actors

반응형