데이터 동기화 기초

김 무무 ㅣ 2024. 10. 1. 23:35

1. 경쟁 상태 (Race condition)

경쟁 상태는 둘 이상의 스레드가 공유 데이터에 동시에 접근하여 예측할 수 없는 결과를 초래하는 상황을 말한다.

 

ex)

#include <iostream>
#include <thread>
int num = 0;

void Increment() {
    for (int i = 0; i < 1000000; i++) {
        num++;  // race condition을 유발할 수 있다.
    }
}

int main() {
    std::thread t1(Increment);
    std::thread t2(Increment);

    t1.join();
    t2.join();

    std::cout << "값: " << num << std::endl;
    // 예상 값은 2000000이지만, 실제로는 이보다 작은 값이 출력된다.
}

 

위 예시에서 `num`은 race condition의 대상이 된다.

두 스레드가 동시에 이 변수를 증가시키려고 하면, 일부 연산이 손실될 수 있다.

 

 

2. 임계 영역(Critical Section)

임계 영역은 여러 스레드가 동시에 접근해서는 안 되는 공유 자원을 접근하는 코드 영역을 말한다.

임계 영역에 대한 접근은 상호 배제(mutual exclusion)를 통해 동기화되어야 한다.

임계 영역의 특성 :

- 한 번에 하나의 스레드만 임계 영역에 진입할 수 있어야 함

- 임계 영역 밖의 스레드는 다른 스레드의 임계 영역 진입을 막을 수 없어야 함

- 임계 영역에 진입하려는 스레드의 대기 시간이 유한해야 함(기아 상태 방지)

 

3. 동기화의 필요성

동기화가 필요한 이유 :

- 데이터 일관성 유지 : 여러 스레드가 동시에 데이터를 수정할 때 데이터의 일관성을 보장

- Race condition 방지 : 예측 가능하고 정확한 결과를 보장

- 교착 상태(Deadlock) 방지 : 적절한 동기화 기법을 사용하여 교착 상태를 예방

- 원자성(Atomicity) 보장 : 특정 연산이 중간에 끊기지 않고 완전히 수행되도록 함

 

4. C++에서의 동기화:

1) std::mutex:

#include <iostream>
#include <mutex>
#include <thread>
int num = 0;
std::mutex mtx;

void Increment() {
    for (int i = 0; i < 1000000; i++) {
        std::lock_guard<std::mutex> lock(mtx);
        num++;
    }
}

int main() {
    std::thread t1(Increment);
    std::thread t2(Increment);

    t1.join();
    t2.join();

    std::cout << "값: " << num << std::endl;
    // 이제 항상 2000000이 출력된다.
}



2) std::atomic:

#include <iostream>
#include <atomic>
#include <thread>
std::atomic<int> num(0);

void Increment() {
    for (int i = 0; i < 1000000; i++) {
        num++;
    }
}

int main() {
    std::thread t1(Increment);
    std::thread t2(Increment);

    t1.join();
    t2.join();

    std::cout << "값: " << num << std::endl;
    // 이제 항상 2000000이 출력된다.
}

 

 

동기화를 통해 race condition을 방지하고 데이터의 일관성을 유지할 수 있다.

하지만 과도한 동기화는 성능 저하를 일으킬 수 있으므로, 사용에 주의해야 한다.

'멀티스레딩' 카테고리의 다른 글

동기화 기법: Atomic 연산  (0) 2024.10.05
메모리 구조와 멀티스레딩  (0) 2024.10.03
스레드 생성과 관리  (0) 2024.09.28
멀티스레딩 기초  (0) 2024.09.28
개요  (0) 2024.09.26