lock_guard 를 활용한다고 해서 세상 모든 dead_lock이 사라지지 않는다.
저번 단원에서 배운 ( lock_guard (RAII) : ) lock 해주고 unlock 안해줘서 생기는 ) DeadLock 은 정말 1차원적인 DeadLock이고 자주 생기지 않는다.
다른 이유 때문에 생기는 DeadLock이 많고, 실제 실무에서 예를 들자면,
MMO 서버에서 서버가 뻗는다면 가장 높은 확률로는 nullptr 크래쉬가 ( 포인터인데 nullptr를 잘 못 참조해서 뻗는 경우 ) 가 있고, DeadLock 문제도 상위권에 있는 문제이다.
오늘만 실습할 클래스를 하나 만들어보자.
쓰레드 t1 은 ProcessSave() 를 실행하면서 user lock을 걸고 있고 이 Lock 은 ProcessSave() 가 종료될때 lock_guard 에 의해 소멸자가 호출되면서 unlock 된다. (RAll 이론 )
반대로 쓰레드 t2 는 ProcessLogin() 함수를 실행하면서 account lock을 걸고 있는데 마찬가지로 ProcessLogin() 함수가 끝날떄 소멸자에 의해 unlock 된다.
두 함수 모두 다음 코드로 서로가 lock을 풀면 들어가려고 기다리고 있기 때문에 dead lock 이 걸렸고,
해결 방법은 간단하다.
1. 순서를 맞춰 주면 된다.
t1을 account Lock 부터 걸어주던,
t2를 user Lock 부터 걸어주던
둘 중에 먼저 들어간 mutex를 잡은 사람이 다른 것도 잡을 수 있게끔 하면 된다.
그러나 멀티 쓰레드 환경에서 이렇게 순서를 맞춰준다는거 자체가 굉장히 어려운 일이다.
Dead Lock 이 짜증나는 이유는 어쩔때는 발생 하고 어쩔때는 발생하지 않기 때문에 짜증이 난다
위의 예시에서 Fun1() 이나 Func2() 의 for문의 반복횟수를 1로 줄인다면 발생하지 않을때가 많을 것이다.
그래서 개발 단계에서는 발견 못하다가 실제 live 상황에서 동접이 많아 질때만 발견할 가능성도 있다.
그렇다면 이 순서를 항상 맞춰 줄 수 있는 방법이 있냐? NO
사람들이 많이 사용하는 방법이 있긴 하다.
mutex _mutex 를 바로 사용하는게 아니라 wrapping을 해서 별도의 class 로 만든 다음에 일종의 id를 부여해서 id가 큰애가 무조건 먼저해야되는 거처럼 꼼수를 이용해서 하긴 하는데, 이것도 정확하지는 않다.
결론 부터 말하자면 Dead_lock은 뭔가 미연의 100% 방지하고 그런게 아니라 조심하면서 사용해야한다.
한 가지 팁은
강의 후반부에 강사님는 그럼 어떻게 이걸 해결하는지 직접 강의로 듣기
: graph 알고리즘을 이용해서 dead_lock을 탐지한다. ( 싸이클이 생기면 )
'C++과 언리얼로 만드는 게임 개발 > Part4. Server' 카테고리의 다른 글
★엄청 중요★ Spin Lock ( feat. volatile, compare_exchange_strong() ) | V (0) | 2022.04.29 |
---|---|
Lock 구현 이론 | V (0) | 2022.04.28 |
lock 동기화 방법(2) | V (0) | 2022.04.27 |
Atomic 동기화 방법(1) | V (0) | 2022.04.27 |
쓰레드 생성 | V (0) | 2022.04.15 |