본문 바로가기
Kotlin 공부 노트

[Kotlin-Coroutine] coroutine Mutex(상호배제) 예제를 통한 사용법

by 지게요 2024. 6. 9.
728x90
반응형

이번 포스팅은 이전 개발자분이 만들어 놓은 코드 분석 중 처음 접한 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를 활용하는 것이 중요한 것 같다.

 

반응형