본문 바로가기
게임 서버/[Inflearn_rookiss]올인원_클라&서버 연동

6. 데드 락

by 헛둘이 2023. 12. 11.

데드 락

- 다중 스레드가 서로 필요로 하는 자원을 얻지 못하고 무한히 대기하는 상태
 

데드 락이 발생하는 4가지 조건

1. 상호 배제 : 자원은 한 번에 하나의 스레드만이 사용할 수 있다.
2. 점유 대기 : 하나의 스레드가 자원을 점유한 상태에서 다른 자원을 요청하고 '대기'
3. 비선점 : 스레드가 다른 스레드의 자원을 강제로 빼앗을 수 없음
4. 순환 대기 : 여러 스레드가 자원을 점유하기 위해 서로를 기다리는 상태가 형성
 
데드락을 해소하기 위해서는 위 4가지 조건 중 하나를 제거하면 된다.

#include <iostream>
#include <mutex>
using namespace std;

mutex m1;
mutex m2;

void Thread_1()
{
	for (int i = 0; i < 10000; ++i)
	{
		lock_guard<mutex> guard1(m1);
		lock_guard<mutex> guard2(m2);
	}
}

void Thread_2()
{
	for (int i = 0; i < 10000; ++i)
	{
		lock_guard<mutex> guard2(m2);
		lock_guard<mutex> guard1(m1);
	}
}

int main()
{
	thread t1(Thread_1);
	thread t2(Thread_2);

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

	cout << "Finish!" << endl;

	return 0;
}

- 위는 데드락을 일으키는 대표적인 예제 코드
- 1번 스레드는 뮤텍스 1번, 2번 순으로 락을 잡고, 2번 스레드는 뮤텍스 2번, 1번 순으로 락을 잡는다
- 결과적으로 1번 스레드는 뮤텍스 1번 락을 잡고 2번 락을 얻기 위해 대기하는데, 2번 스레드는 뮤텍스 2번 락을 잡고 1번 락을 얻기 위해 대기하다 보니 옴싹달싹 못하는 상황이 벌어지게 된 것이다. 자신의 락을 포기해야만 다른 스레드가 락을 획득하고, 획득한 후에서야 스코프가 끝나며 미리 선점했던 락을 해제될 수 있기 때문.
- 이 경우를 데드락이라고 하며, 이 경우 현업에서는 일부러 크래쉬를 내면서, 크래쉬 덤프를 따오게 되고 그 덤프를 통해 어디서 데드락이 발생했는지 확인할 수 있다고 한다.
- 이 문제를 해결하기 위해서 한 스레드에서 미리 선점하고 있던 락을 포기할 순 있겠지만, 락을 포기했다는건 오랜 시간 기다렸다는 뜻이고, 그 기다리는 시간이 온라인 게임에선 치명적이기 때문에 적절한 조치는 아니다.
- 가장 일반적인 조치는 두 개의 스레드의 락을 거는 순서를 맞춰주는 것.
- 그런데 현업에서는 이조차 어려운 경우가 많은데, 한 클래스의 함수에서 락을 걸고 그 락 안에서 호출된 다른 클래스의 함수에서 또 락을 걸고 등등 이런 복잡한 상황에서 순서에 맞게 락을 걸고 푸는 것은 예측할 수 없다.
- 강의에서는 락이 걸린 시점에서 또 다른 부분에 락을 걸때 그래프에 등록하고 그래프가 사이클이 생기는지를 확인해서
언젠가 락 때문에 데드락이 발생하는지를 구현할 수 있다고 한다!
  
 
 

'게임 서버 > [Inflearn_rookiss]올인원_클라&서버 연동' 카테고리의 다른 글

8. 스마트 포인터  (2) 2023.12.11
7. 이벤트와 조건변수  (0) 2023.12.11
5. 스핀 락  (0) 2023.12.11
4. Lock 기초  (0) 2023.12.11
3. CPU 파이프라인 및 공유 자원  (0) 2023.12.11

댓글