1. Lock이란
멀티스레딩 환경에서 공유 자원에 대한 접근을 제어하는 동기화 메커니즘
Lock의 주요 목적은 여러 스레드가 동시에 같은 자원에 접근하는 것을 방지하여 데이터의 일관성을 유지하는 것이다.
주요 Lock 종류:
1) 상호 배제 Lock (Mutual Exclusion Lock)
- 가장 기본적인 형태의 Lock
- 한 번에 하나의 스레드만 임계 영역에 진입 가능
2) 읽기-쓰기 Lock (Read-Write Lock)
- 읽기 작업과 쓰기 작업을 구분
- 여러 스레드가 동시에 읽기 가능, 쓰기는 독점적으로 수행
3) 재진입 가능 Lock (Reentrant Lock)
- 같은 스레드가 이미 획득한 Lock을 다시 획득 가능
- 재귀적 알고리즘이나 중첩된 메서드 호출에서 유용
2. Lock 구현 방법
1) 스핀락 기반 구현
Lock을 획득할 때까지 반복해서 시도하는 방식
ex)
#include <iostream>
#include <thread>
#include <vector>
#include <atomic>
#include <chrono>
using namespace std;
class SpinLock {
atomic<bool> flag = { false };
public:
void Lock() {
while (flag.exchange(true, memory_order_acquire));
}
void Unlock() {
flag.store(false, memory_order_release);
}
};
class SharedResource {
private:
int value;
SpinLock spinlock;
public:
SharedResource() : value(0) {}
void Increment() {
spinlock.Lock();
value++;
// 작업
this_thread::sleep_for(chrono::milliseconds(1));
spinlock.Unlock();
}
int GetValue() const { return value; }
};
void Worker(SharedResource& resource, int id, int iterations) {
for (int i = 0; i < iterations; i++) {
resource.Increment();
cout << "스레드 " << id << " 실행" << endl;
}
}
int main() {
SharedResource resource;
vector<thread> threads;
const int THREADS_COUNT = 10;
const int ITERATIONS_PER_THREAD = 50;
for (int i = 0; i < THREADS_COUNT; ++i)
threads.emplace_back(Worker, ref(resource), i, ITERATIONS_PER_THREAD);
for (auto& t : threads)
t.join();
cout << "스레드 수 : " << THREADS_COUNT << endl;
cout << "예상값 : " << (THREADS_COUNT * ITERATIONS_PER_THREAD) << endl;
cout << "결과값 : " << resource.GetValue() << endl;
}
2) 대기 큐 기반 구현
운영체제의 스케줄러를 활용하여 대기 중인 스레드를 관리하는 방식
ex)
class MutexLock {
atomic<bool> locked = { false };
queue<thread::id> waitQueue;
public:
void Lock() {
while (locked.exchange(true, memory_order_acquire)) {
waitQueue.push(this_thread::get_id());
this_thread::yield();
}
}
void Unlock() {
locked.store(false, memory_order_release);
if (!waitQueue.empty()) {
waitQueue.pop();
}
}
};
3. Lock의 장단점
장점:
- 간단하고 직관적인 동기화 메커니즘 제공
- 데이터 일관성 보장
단점:
1) 데드락 위험
- 여러 Lock을 사용할 때 발생 가능
- 예방법: Lock 획득 순서를 일관되게 유지
2) 성능 오버헤드
- Lock 획득/해제에 따른 추가 연산 필요
- 경쟁 상황에서 대기 시간 발생
3) 우선순위 역전 문제
- 낮은 우선순위 스레드가 Lock을 보유한 채 선점되면, 높은 우선순위 스레드가 대기
'멀티스레딩' 카테고리의 다른 글
데드락(Deadlock) (1) | 2024.10.07 |
---|---|
동기화 기법: Mutex (0) | 2024.10.05 |
동기화 기법: Atomic 연산 (0) | 2024.10.05 |
메모리 구조와 멀티스레딩 (0) | 2024.10.03 |
데이터 동기화 기초 (0) | 2024.10.01 |