mutex와 semaphore
운영체제를 배울때 한번쯤은 들어보셨을 겁니다.
그중에 코루틴에서는 Mutex를 지원하는데
어떻게 사용하는 걸까요?
var counter =0
fun test() = runBlocking {
val mutex = Mutex()
GlobalScope.massiveRun {
counter++
}
println("Counter = $counter")
}
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")
}
이코드와 같이 많은 코루틴에서 같은 자원에 접근하여
수정한다면 어떻게 될까요?
과연 10만번 전부 수정 가능할까요?
Completed 100000 actions in 25 ms
Counter = 21647
정답은 불가능 하다입니다.
공유 자원을 동시에 접근하려니 동작이 제대로 실행이 안됐죠?
이럴 때 사용하는 것이 Mutex입니다!
var counter =0
fun test() = runBlocking {
val mutex = Mutex()
GlobalScope.massiveRun {
mutex.withLock {
counter++
}
}
println("Counter = $counter")
}
이와 같이 Mutex를 만들어주고 수정할 자원을 withLock으로 감싸주면 됩니다.
간단하죠?
이렇게 하는 것만으로도 정상 동작해요!
Completed 100000 actions in 136 ms
Counter = 100000
왜그럴까요?
위와 같은 상황에서는
수 많은 코루틴이 한 자원을 사용하려고 경쟁상태에 돌입하게 되는데
Mutex를 이용하게 되면
상호 배제(Mutual exclusion)를 통해 자원에 접근할땐 하나의 코루틴만
접근 가능하도록 해서 경쟁상태를 해결하게 됩니다.
코루틴을 사용하다보면 수많은 코루틴을 동시에 실행해서
본의아니게 경쟁상태가 되는 경우가 생깁니다.
이럴때 mutex를 잘 사용하면
도움이 되겠죠?