티스토리 뷰

락(Lock)은 멀티스레드 및 멀티프로세스 환경에서 동기화(Synchronization)와 데이터 정합성(Consistency)을 보장하는 핵심 기술입니다.
그러나 잘못 사용하면 성능 저하, 데드락(Deadlock), 락 경합(Lock Contention) 등의 문제가 발생할 수 있습니다.

효율적인 락 사용을 위해 불필요한 락을 최소화하고, 적절한 락 전략을 선택하는 것이 중요합니다.
다음은 락 관련 성능 최적화 기법을 정리한 내용입니다.

 

 

 

1. 락 사용 시 발생하는 성능 문제

락은 공유 자원에 대한 동시 접근을 제어하는 과정에서 성능 저하를 유발할 수 있습니다.
주요 성능 문제는 다음과 같습니다.

  1. 락 경합(Lock Contention)
    • 여러 스레드 또는 프로세스가 동일한 락을 획득하려 할 때 충돌이 발생하는 현상입니다.
    • 대기 시간이 증가하고, 전체 시스템의 처리 속도가 감소할 수 있습니다.
  2. 데드락(Deadlock)
    • 두 개 이상의 스레드가 서로의 락 해제를 기다리는 교착 상태에 빠지는 현상입니다.
    • 데드락이 발생하면 시스템이 정상적으로 동작하지 않으며, 강제 종료가 필요할 수도 있습니다.
  3. 기아 상태(Starvation)
    • 일부 스레드가 지속적으로 락을 획득하지 못하는 현상입니다.
    • 공정한(Fair) 락 정책이 필요할 수 있습니다.
  4. 락 유지 시간 증가(Lock Holding Time)
    • 락을 장기간 유지하면 다른 스레드가 대기하는 시간이 증가하여 성능이 저하됩니다.
  5. 캐시 동기화 문제(Cache Coherency Overhead)
    • 멀티코어 환경에서는 공유 변수에 대한 락이 CPU 캐시 동기화 문제를 유발할 수 있습니다.
    • CPU의 메모리 일관성 모델에 따라 성능이 영향을 받을 수 있습니다.

 

 

 

2. 락 성능 최적화 기법

2.1. 락 범위를 최소화하기 (Minimize Lock Scope)

락을 적용하는 범위를 최소화하면 스레드 간 충돌을 줄이고, 성능을 개선할 수 있습니다.

  • 불필요한 공유 데이터 줄이기
    • 공유 데이터가 많을수록 락을 획득하는 스레드가 증가하여 경합이 발생합니다.
    • 가능하면 스레드별로 독립적인 데이터를 사용하는 것이 좋습니다.
  • 락을 필요한 코드 블록에서만 사용
    • 락을 유지하는 시간이 길면 성능이 저하될 수 있습니다.
    • 락을 짧은 시간 동안만 유지하도록 코드를 개선해야 합니다.

잘못된 예제 (락 유지 시간이 길어지는 경우)

std::mutex mtx;

void processData() {
    mtx.lock();  // 락이 너무 큰 범위를 차지함
    expensiveComputation();  // 락을 유지하면서 오래 실행됨
    mtx.unlock();
}

개선된 예제 (락 범위를 최소화)

std::mutex mtx;

void processData() {
    expensiveComputation(); // 락 없이 실행
    mtx.lock();
    updateSharedResource(); // 필요한 부분에서만 락 사용
    mtx.unlock();
}

 

2.2. 락 경합 줄이기 (Reduce Lock Contention)

여러 스레드가 동일한 락을 경쟁하지 않도록 락을 분산하거나, 다른 동기화 방법을 고려해야 합니다.

  • 락 분할(Lock Splitting) 사용
    • 하나의 큰 락을 여러 개의 작은 락으로 나누어 성능을 향상시킬 수 있습니다.
    • 예를 들어, 여러 개의 데이터 구조를 다룰 경우 각 데이터 구조별로 별도의 락을 사용하면 성능이 향상됩니다.

잘못된 예제 (하나의 락으로 모든 작업 처리)

std::mutex mtx;
std::vector<int> data1;
std::vector<int> data2;

void processData() {
    mtx.lock();  
    data1.push_back(10);
    data2.push_back(20);
    mtx.unlock();
}

개선된 예제 (락 분할 적용)

std::mutex mtx1, mtx2;
std::vector<int> data1;
std::vector<int> data2;

void processData() {
    mtx1.lock();
    data1.push_back(10);
    mtx1.unlock();

    mtx2.lock();
    data2.push_back(20);
    mtx2.unlock();
}

 

2.3. 락을 피하는 기법 사용 (Avoid Locks When Possible)

  • 락 없는 알고리즘(Lock-Free Algorithm) 사용
    • std::atomic과 같은 원자적 연산을 사용하여 락 없이 동기화를 수행할 수 있습니다.
    • Compare-And-Swap (CAS) 같은 기술을 활용하면 성능이 크게 향상될 수 있습니다.

락을 사용한 방식 (비효율적)

std::mutex mtx;
int counter = 0;

void increment() {
    std::lock_guard<std::mutex> lock(mtx);
    counter++;
}

락을 제거한 방식 (CAS 사용)

std::atomic<int> counter(0);

void increment() {
    counter.fetch_add(1, std::memory_order_relaxed);
}
  • 읽기-쓰기 락(Read-Write Lock) 사용
    • 읽기 작업이 많을 경우 읽기 작업은 여러 스레드가 동시에 실행 가능하도록 하고, 쓰기 작업은 단일 스레드만 가능하도록 조정할 수 있습니다.
std::shared_mutex rwLock;
std::vector<int> sharedData;

void readData() {
    std::shared_lock<std::shared_mutex> lock(rwLock); // 읽기 락
    std::cout << "데이터 읽기 중\n";
}

void writeData() {
    std::unique_lock<std::shared_mutex> lock(rwLock); // 쓰기 락
    sharedData.push_back(100);
    std::cout << "데이터 쓰기 완료\n";
}

 

2.4. 공정한 락 정책 사용 (Fair vs. Unfair Lock)

  • 공정한 락(Fair Lock)은 락을 요청한 순서대로 스레드가 락을 획득할 수 있도록 합니다.
  • 비공정한 락(Unfair Lock)은 락을 해제하는 순간, 대기 중인 스레드가 아니라 즉시 실행 가능한 스레드가 락을 먼저 획득할 수도 있습니다.

비공정한 락 (성능은 좋지만 기아 상태 발생 가능)

std::mutex unfairLock;

공정한 락 (FIFO 방식 적용)

std::timed_mutex fairLock;

 

2.5. 락 해제 최적화 (Optimize Lock Release)

  • 락을 명확하게 해제해야 하며, 불필요한 경우에는 조기에 해제하는 것이 중요합니다.
  • std::lock_guard 또는 std::unique_lock을 사용하면 예외 발생 시에도 자동으로 락이 해제됩니다.

잘못된 락 해제 방식

std::mutex mtx;

void process() {
    mtx.lock();
    if (someCondition()) return; // 여기서 락이 해제되지 않음 (데드락 위험)
    mtx.unlock();
}

개선된 락 해제 방식

std::mutex mtx;

void process() {
    std::lock_guard<std::mutex> lock(mtx);
    if (someCondition()) return; // 자동으로 락이 해제됨
}

 

 

3. 결론

락은 필수적인 동기화 기술이지만, 잘못 사용하면 성능 저하와 데드락을 유발할 수 있습니다.
최적의 성능을 유지하기 위해서는 락의 범위를 최소화하고, 락을 피하는 기법을 적극 활용하며, 공정한 락 정책을 고려해야 합니다.
또한, 락을 자동으로 해제하는 구조를 적용하여 실수로 인한 데드락 발생을 방지하는 것이 중요합니다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/03   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
글 보관함