⚠️ 해당 포스팅은 인프런 공룡책 강의를 듣고 개인적으로 정리하는 글입니다. 정확하지 않은 정보가 있을 수 있으니 주의를 요합니다.
Chapter 8 Deadlocks
데드락(Deadlock)은 모든 프로세스들이 다른 프로세스의 이벤트를 대기하고 있을 때를 일컫는다.
즉, waiting
상태에 있는 스레드가 리소스를 요청했을 때, 리소스가 다른 waiting
상태의 스레드에 의해 점유되어 있어 다시는 자신의 상태를 바꾸지 못하는 경우를 의미한다.
다른 프로세스가 종료되는 것을 무한정 대기하는 상태
프로세스 집합에 있는 모든 프로세스가, 집합 내에 한 프로세스의 이벤트를 기다리고 있는 경우
한정된 리소스로 구성된 시스템을 여러 스레드로 공유해야 하는 상황을 생각해보자.
: 리소스 타입은 여러 개의 동일한 인스턴스 타입으로 구성되어 있다.
: (e.g., CPU cycles, files, and I/O devices(such as printers, drive, etc.)
한 스레드(혹은 프로세스)가 어떤 리소스의 한 인스턴스를 요청할 때, 동일 리소스의 인스턴스를 할당하여 요청을 충족한다.
리소스의 타입이 중요하고, 안의 인스턴스의 개수는 중요하지 않다.
🥲 이 부분을 이해하는데 굉장히 애먹었는데, 맞는 이해인지는 모르겠지만 일단 적는다.
프린터를 리소스라고 하면, 프린터 내의 인스턴스는 복사, 출력등이 있을 것이다. 이 프린터에 프로세스가 접근하면, 프린터 내의 인스턴스 중 하나를 할당하여 프로세스의 요청을 처리하는 것이다.
프로세스가 리소스를 점유하고 있지 않으면, 애초에 데드락이 일어나지 않음.
선점이 되어버리면 프로세스가 실행을 종료하니 데드락이 일어나지 않음.
V
라고 칭하며, V
에는 두 가지 타입이 있다.T
: 스레드 집합R
: 리소스 집합E
라고 칭하며, 역시 두 가지 타입이 있다.문제 발생을 무시한다.
: 발생하지 않을 것이라고 가정한다. (🙏 기도한다.)
데드락을 방지 혹은 회피하기 위한 프로토콜을 사용한다.
: 프로토콜을 이용하여 어떤 상황에서도 데드락에 빠지지 않게 설정하는 것이다.
: 데드락 완전 방지, 데드락 회피 등의 방법이 있다.
시스템이 데드락 상황에 빠진 것을 확인했을 때 회복한다.
Mutual Exclusion
: 리소스 접근 시 여러 프로세스가 접근하게 해버리는 것이다.
: mutex
락을 여러 프로세스가 공유하면 대참사가 날 것이므로, 본질적으로 불가능한 방법이다.
Hold and Wait
: 프로세스가 리소스를 점유하고 있지 못하게 하는 방법이다.
: 프로세스가 리소스를 요청할 때, 가지고 있는 리소스를 모두 내려놓고 리소스를 요청한다.
: 이 후 획득하면 가지고 있던 리소스를 다시 요청한다.
: 딱 봐도 실용적이지 않다.
No premmption
: 다른 프로세스가 리소스를 점유하고 있을 때, 이를 선점하여 실행하는 방법이다.
: 선점당한 프로세스는 어떤 작업을 하든 일단 waiting
상태로 돌입한다.
: 다시 프로세스를 실행하려면 이전 리소스와 새 리소스를 되찾아야만 다시 시작할 수 있다.
: 이 역시 실용적이지 않은 방법이다.
Circular Wait
: 그나마 실용적인 방법으로, 리소스에 순서를 부여하는 방법이다.
: 각 프로세스가 순서대로 리소스를 요청하게끔 요구한다.
: 우선순위를 부여하는 것과 마찬가지가 되어 기아 상태가 발생할 가능성이 높다.
: 위의 사진을 보면 알겠지만 데드락을 완벽하게 방지하는 것도 아니다.
결론 : 모두 실용적인 방법이 아니다.
n
: 시스템에 있는 스레드의 수m
: 시스템에 있는 리소스의 수Available
: 사용 가능한 리소스의 인스턴스 수 vector
avaliable[1] = 5 ->: 1번 리소스의 인스턴스는 5개
Max
: 각 스레드가 요청할 인스턴스의 최대 수 matrix
Max[3][5] = 5 -> 3번 스레드는 5번 리소스의 인스턴스를 최대 5개 요청 가능
Allocation
: 각 스레드에 할당된 리소스의 수 matrix
Allocation[1][3] = 3 -> 1번 스레드가 6번 리소스의 인스턴스를 3개 할당 받았음
Need
: 앞으로 요청할 리소스의 수 matrix
Max[3][5] - Allcation[1][3] = Need[2][2]
Request
: 스레드가 요청한 리소스의 수 matrix
Request[4][6] = 5 -> 4번 스레드가 6번 리소스의 인스턴스 5개를 요청함
Work
, Finish
벡터를 아래와 같이 초기화한다.Work
= Available
, Finish[i] = false
Finish[i] == false
, Need[i] <= Work
Work
= Work
+ Allocation[i]
Finish[i]
= true
Finish[i]
가 모두 true
라면, 안전한 상태라는 의미이다.Request[i] <= Need[i]
이면 2번으로 간다.Max
보다 더 많은 양의 리소스를 요청했다는 것을 의미한다.Request[i] <= Available[i]
이면 3번으로 간다.Work
= Available
로 초기화하고, Allocation[i]
가 0이면 Finish[i]
를 true
로 설정한다.(스레드가 리소스를 점유하고 있지 않다는 뜻이므로 체크하는 것이 무의미하다. 즉, 프리패스 🏎)
Finish[i] == false
, Request[i] <= Work
Work = Work + Allocation[i]
, Finish[i] == true
Finish[i] == false
이면 해당 스레드는 데드락이 발생한 상태임을 의미한다.