1. Dead Lock
1.1 Dead Lock
void worker1(int& counter, std::mutex& m1, std::mutex& m2)
{
for (int i = 0; i < 10000; i++)
{
std::lock_guard<std::mutex> lock1(m1);
std::lock_guard<std::mutex> lock2(m2);
counter++;
}
}
void worker2(int& counter, std::mutex& m1, std::mutex& m2)
{
for (int i = 0; i < 10000; i++)
{
std::lock_guard<std::mutex> lock1(m2);
std::lock_guard<std::mutex> lock2(m1);
counter++;
}
}
int main()
{
vector<std::thread> workers;
std::mutex m1;
std::mutex m2;
int counter = 0;
workers.push_back(std::thread(worker1, std::ref(counter), std::ref(m1), std::ref(m2)));
workers.push_back(std::thread(worker2, std::ref(counter), std::ref(m1), std::ref(m2)));
for (int i = 0; i < 2; i++) workers[i].join();
cout << counter << endl;
}
- 위의 경우를 본다면 프로그램이 끝나지 않아 강제로 종료해야만 함
- worker1, worker2의 mutex를 얻는 순서
- worker1::m1 Lock → worker2::m2 Lock → worker1::m2 Lock? or worker2::m1 Lock?
- 둘다 잠겨버리는 상황 발생 → Dead Lock 상태
1.2 Try Lock
- try_lock은 mutex가 만약 lock을 할 수 있으면 true, 할 수 없으면 false를 반환
- 만약 할 수 없다가 나온다면 잠궜던 mutex를 다시 풀어주고 처음부터 실행
void worker2(int& counter, std::mutex& m1, std::mutex& m2)
{
for (int i = 0; i < 10000; i++)
{
while (true)
{
m2.lock();
if (!m1.try_lock())
{
m2.unlock();
continue;
}
m2.unlock();
m1.unlock();
break;
}
counter++;
}
}
1.3 데드락 상황을 피하기 위한 조건
- 중첩된 Lock을 사용하는 것을 피함
- Lock을 소유하고 있을 때 유저 코드를 호출하는 것을 피함
- Lock 들을 언제나 정해진 순서로 획득
'Create Game > [Window API] Game Client & Game Server' 카테고리의 다른 글
[SERVER] Condition Variable (0) | 2023.01.03 |
---|---|
[SERVER] Producer & Consumer (0) | 2023.01.03 |
[SERVER] MUTEX (0) | 2023.01.03 |
[SERVER] Race Condition (0) | 2023.01.03 |
[SERVER] Thread (0) | 2023.01.03 |