2025년 4월 17일 목요일

5-2-1강: 동시성 제어 기법(Mutex)

 Rust에서 스레드와 Mutex로 전역 변수 안전하게 공유하기


Rust에서는 여러 스레드가 동시에 데이터를 다룰 경우, **경쟁 상태(Race Condition)**를 피하기 위해 Mutex를 자주 사용합니다. 
아래 예제는 100개의 스레드가 하나의 전역 변수 counter를 안전하게 1씩 증가시키는 코드입니다.

use std::thread;
use std::sync::Mutex;

//Mutex 는 여러 스레드가 공유자원에 동시에 접근하지 못하도록 막는 기법
//Mutex 는 잠금(lock)와 해제(unlock)의 두 가지 상태가 존재
static counter: Mutex<i32> = Mutex::new(0); // counter를 전역변수로 정의

fn inc_counter() {
    // lock을 걸고 접근 권한을 획득함
    //unwrap()은 lock 실패 시 패닉을 발생시킴.
    let mut num = counter.lock().unwrap();
    *num = *num + 1; // 자원에 접근하려면 *키워드를 사용한다.
} // inc_counter를 벗어나는 순간 counter는 unlock됩니다.

fn main() {
    let mut thread_vec = vec![];

    // _ 는 변수 이름이 정의되어야 할 부분에서 변수명을 생략할 때 사용한다.
    for _ in 0..100 {
        let th = thread::spawn(inc_counter);
        thread_vec.push(th);
    }

    //각 스레드가 끝날 때까지 기다림.
    for th in thread_vec {
        //join()을 하지 않으면 메인 함수가 먼저 끝날 수도 있음.
        th.join().unwrap();
    }

    // 마지막으로 counter의 값을 lock으로 가져와 출력.
    println!("결과: {}", *counter.lock().unwrap());
}

/*실행결과
결과: 100
*/

핵심 포인트

  • Mutex<i32>를 사용해 여러 스레드가 동시에 안전하게 공유 자원에 접근 가능

  • lock().unwrap()으로 lock을 획득하고, 해제는 스코프 종료 시 자동

  • join()으로 메인 스레드가 하위 스레드를 기다림

왜 Mutex가 필요한가?

스레드가 동시에 값을 수정하면 예상치 못한 오류가 발생할 수 있습니다. 

Mutex는 이런 충돌을 방지하는 락(lock) 메커니즘을 제공합니다.

댓글 없음:

댓글 쓰기