본문 바로가기

언어/Rust

[ Rust ] 데이터 경합(data race)에 대해서 알아보기

반응형

데이터 레이스(Data Race)는 여러 스레드가 동시에 같은 메모리 위치를 읽거나 쓰려고 할 때 발생하는 문제입니다. 이 상황에서 적어도 하나의 스레드가 데이터를 쓰려고 하면 데이터 레이스가 발생합니다. 데이터 레이스는 프로그램의 동작을 예측하기 어렵게 만들며, 심각한 버그를 초래할 수 있습니다.

러스트(Rust)는 이러한 데이터 레이스 문제를 컴파일 타임에 방지하기 위해 고유한 메모리 안전성 모델을 채택하고 있습니다. 러스트의 소유권 시스템은 데이터 레이스를 방지하는 중요한 역할을 합니다. 컴파일러는 동일한 메모리 위치에 동시에 접근하려는 여러 스레드가 있는지 확인하고, 만약 가능성이 있다면 컴파일 에러를 발생시킵니다.

예제: 데이터 레이스가 발생하는 코드 (Rust가 아니었더라면)

use std::thread;

fn main() {
    let mut data = vec![1, 2, 3];

    let handle = thread::spawn(|| {
        data.push(4);  // 데이터 레이스 발생 가능
    });

    data.push(5);  // 데이터 레이스 발생 가능

    handle.join().unwrap();
}

위 코드는 Rust에서 컴파일되지 않습니다. 컴파일러는 data가 여러 스레드에 의해 동시에 접근될 수 있다는 사실을 인지하고 이를 막습니다.

예제: 안전한 코드

use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let data = Arc::new(Mutex::new(vec![1, 2, 3]));

    let data_clone = Arc::clone(&data);
    let handle = thread::spawn(move || {
        let mut data = data_clone.lock().unwrap();
        data.push(4);
    });

    {
        let mut data = data.lock().unwrap();
        data.push(5);
    }

    handle.join().unwrap();
}

이 예제에서는 ArcMutex를 사용하여 안전하게 데이터를 공유하고 수정합니다. Arc는 여러 스레드 간에 데이터를 안전하게 공유할 수 있도록 참조 카운팅(reference counting)을 제공하고, Mutex는 한 번에 하나의 스레드만 데이터에 접근할 수 있도록 보장합니다.

이렇게 Rust는 강력한 메모리 안전성을 통해 데이터 레이스를 방지하며, 개발자가 보다 안전한 병렬 프로그래밍을 할 수 있도록 돕습니다.

반응형