이번 포스팅은 이전 개발자분이 만들어 놓은 코드 분석 중 처음 접한 Coroutine의 Mutex를 사용한 코드가 있어 알아둬야겠다고 생각해서 적어본다.
우선 아래 정리를 통해 Mutex대해 알아보자!
# Mutex란? (특징)
- Mutual Exclusion의 약자로 "상호 배제"를 의미한다.
("상호 배제"에 관해서는 시간이 난다면 따로 블로그 포스팅을 해야겠다..)
- 여러 코루틴이 동시에 공유 자원에 접근하지 못하게 하여 데이터 일관성을 유지시켜 준다.
- 한 코루틴이 Mutex를 획득하면, 다른 코루틴은 해당 Mutex가 해제될 때까지 대기하게 된다.
# Mutex 사용 이유
그럼 Mutex는 왜 사용하냐? 위 Mutex에 특징과 거의 비슷한데 간단하게 정리하면 이유는 아래와 같다
여러 코루틴이 동시에 공유 자원에 접근하면 데이터 충돌이 발생할 수 있기 때문에 Mutex를 사용한다.
# Mutex 사용 예제
mutex가 간략하게 어떤 건지 알았으면 이제 사용법을 알아볼 차례이다.
아래 예제는 2개의 코루틴(job1, job2)에서 동시에 공유 자원(count)을 접근하는 예제이다.
## mutex 사용 전
fun main() = runBlocking {
var count = 0
val job1 = GlobalScope.launch {
repeat(10000) {
count++ // Mutex를 사용하지 않음
}
}
val job2 = GlobalScope.launch {
repeat(10000) {
count++ // Mutex를 사용하지 않음
}
}
job1.join() // 첫 번째 코루틴이 완료될 때까지 대기
job2.join() // 두 번째 코루틴이 완료될 때까지 대기
println("최종 count 값: $count")
}
사용 전 코드를 살펴보면 count이라는 변수에 job1과 job2이 동시 접근과 작업을 하고 있다.
그렇게 되면 위에서 말한 문제점이 나오게 된다.
기대하는 값은 당연히 20000이 나와야 한다.
하지만 실제 출력값을 보면 20000보다 더 작은 값을 출력할 가능성이 매우 높다.
그 이유는 count 변수에 여러 코루틴이 동시에 접근하여 증가시키기 때문에 데이터 경합(rece condition)이 발생하기 때문이다.
그럼 이제 mutex를 사용해 해당 문제를 해결해 보겠다.
## mutex 사용
사용법은 간단하다.
1. Mutex 객체를 만든다.
val mutex = Mutex()
2. withLock 스코프 안에 작업을 실행시켜 준다.
val mutex = Mutex()
mutex.withLock {
// 작업 실행
}
전체 코드
fun main() = runBlocking {
// Mutex 객체 생성
val mutex = Mutex()
var count = 0
val job1 = GlobalScope.launch {
repeat(10000) {
mutex.withLock {
// Mutex 사용
count++
}
}
}
val job2 = GlobalScope.launch {
repeat(10000) {
mutex.withLock {
// Mutex 사용
count++
}
}
}
job1.join() // 첫 번째 코루틴이 완료될 때까지 대기
job2.join() // 두 번째 코루틴이 완료될 때까지 대기
println("최종 count 값: $count")
}
이처럼 mutex.withLock를 사용하여 데이터 경합(rece condition) 문제를 해결해 주었다.
withLock 스코프 안의 코드는 한 번에 하나의 코루틴만 실행시킬 수 있다.
# 마무리
이번 포스팅에서는 Coroutine의 Mutex에 대해 알아보고, 이를 사용하여 여러 코루틴이 동시에 공유 자원에 접근할 때 발생할 수 있는 데이터 경합 문제를 해결하는 방법을 배웠다.
Kotlin Coroutine에서 동시성 문제를 안전하게 처리하려면 Mutex를 활용하는 것이 중요한 것 같다.
'Kotlin 공부 노트' 카테고리의 다른 글
[Kotlin Flow] StateFlow vs SharedFlow 예제와 함께 차이점 알아보기! (0) | 2024.11.30 |
---|---|
[Kotlin Flow] 코틀린 Flow란? - 예제와 함께 알아보기 (1) | 2024.09.17 |
[Android-Kotlin] Groovy DSL -> Kotlin DSL Migration(코틀린 DSL로 의존성 관리 마이그레이션), Kotlin DSL이란? (2) | 2023.10.29 |
DTO, DAO, VO에 알아보자! (0) | 2023.03.30 |
코틀린의 오브젝트란? (object, companion object) (0) | 2022.02.17 |