1. 데드락(Deadlock)
여러 스레드가 서로의 공유 자원에 접근하려 할 때 락으로 인해 무한정 대기하는 상태.
(1) 발생 조건
- lock 이후 unlock 하지 않았을 때
- 순환 대기 상태일 때
(2) 코드 실험 - 순환 대기
mutex m1;
mutex m2;
vector<int> v;
void Thread_1()
{
for (int i = 0 ; i < 10000 ; i++)
{
lock_guard<mutex> lockGuard1(m1);
lock_guard<mutex> lockGuard2(m2);
}
}
void Thread_2()
{
for (int i = 0; i < 10000; i++)
{
lock_guard<mutex> lockGuard2(m2);
lock_guard<mutex> lockGuard1(m1);
}
}
int main()
{
thread t1(Thread_1);
thread t2(Thread_2);
t1.join();
t2.join();
cout << "END" << endl;
}
스레드 1은 m1에 lock을 걸었고 스레드 2는 m2에 lock을 걸었다.
이 상태에서 각 스레드가 상대방 스레드의 락을 획득하려고 하기 때문에 교착 상태(데드락)에 빠지게 된다.
(3) 데드락 해제
위의 데드락 상태를 해제하는 방법은 락 순서를 서로 맞춰주는 방법이 있다.
void Thread_1()
{
for (int i = 0 ; i < 10000 ; i++)
{
lock_guard<mutex> lockGuard1(m1);
lock_guard<mutex> lockGuard2(m2);
}
}
void Thread_2()
{
for (int i = 0; i < 10000; i++)
{
lock_guard<mutex> lockGuard1(m1);
lock_guard<mutex> lockGuard2(m2);
}
}
2. 데드락을 방지하는 방법
데드락을 방지하는 것은 어렵다. 대부분은 해당 상황이 발생한 이후 데드락을 해제하게 될 것이다.
(1) 락 순서를 동일하게 유지하기
가장 간단한 해결 방법이다.
(2) 설계 시 락에 고유 ID를 설정하기
락 마다 고유 ID를 설정하여 다른 락을 잡지 못하게 하는 방법이다.
단, 락이 적을 때에는 효과적이나 락이 많을때는 관리가 불가능하다.
(3) 타임 아웃
일정 시간이 지나면 스레드가 락을 해제하도록 설정한다.
(4) 순환(Cycle)을 해제하기
그래프를 만들어 추적하여 순환 구조가 형성되면 탐지하여 해제하는 방법을 사용할 수 있다.
'서버 프로그래밍 > 멀티 스레드' 카테고리의 다른 글
1-9. 스마트 포인터(shared_ptr, weak_ptr, enable_shared_from_this) (0) | 2023.11.28 |
---|---|
1-8. 생산자-소비자 패턴, 이벤트와 조건 변수(Condition Variable) (0) | 2023.11.28 |
1-6. CAS(Compare And Swap), 스핀 락(Spin Lock) (0) | 2023.11.24 |
1-5. 락 (Lock), 뮤텍스(mutex), RAII 패턴, lock_guard (0) | 2023.11.24 |
1-4. 공유 자원과 경쟁 조건 (0) | 2023.11.23 |