1일 1CS(Computer Science)

교착 상태에 대해서 설명해주세요.

표자 2025. 6. 4. 09:51

💀 교착상태(Deadlock)란?

🤔 교착상태가 뭐죠?

카페에서 두 친구가 각각 포크와 나이프를 하나씩 들고 있는데, 음식을 먹으려면 둘 다 필요한 상황이라면?

  • A는 포크를 들고 나이프를 기다림
  • B는 나이프를 들고 포크를 기다림
  • 결과: 둘 다 영원히 기다리게 됨 😱

이게 바로 교착상태입니다! 두 개 이상의 프로세스가 서로의 자원을 기다리며 무한정 대기하는 상태예요.

 

🔍 교착상태 발생 4가지 조건

모든 조건이 동시에 만족되어야 교착상태가 발생해요

1️⃣ 상호 배제 (Mutual Exclusion)

  • 한 번에 하나의 프로세스만 자원 사용 가능
  • 예: DB 연결, 파일 쓰기 권한

2️⃣ 점유 대기 (Hold and Wait)

  • 자원을 가진 채로 다른 자원을 기다림
  • 예: A 테이블 락을 걸고 B 테이블 락을 기다리는 상황

3️⃣ 비선점 (Non-preemption)

  • 강제로 자원을 뺏을 수 없음
  • 예: 트랜잭션이 완료될 때까지 락 유지

4️⃣ 원형 대기 (Circular Wait)

  • 프로세스들이 원형으로 서로를 기다림
  • 예: A → B → C → A 순서로 자원 대기

🛠️ 해결 방법들

1️⃣ 순서 정하기

// 좋은 예시 - 항상 같은 순서로 락 획득
async function safeTask() {
  await mutex1.acquire(); // 항상 1번 먼저
  await mutex2.acquire(); // 그 다음 2번
  // 작업 수행
  mutex2.release();
  mutex1.release();
}

2️⃣ 타임아웃 설정

// 타임아웃으로 무한 대기 방지
async function taskWithTimeout() {
  try {
    await mutex.acquire({ timeout: 5000 }); // 5초 대기
    // 작업 수행
  } catch (error) {
    console.log('락 획득 실패, 재시도 로직 실행');
  }
}

🌐 실제 웹 개발에서 주의사항

Database 트랜잭션

  • 여러 테이블을 업데이트할 때 항상 같은 순서로 접근
  • 트랜잭션 타임아웃 설정 필수

API 호출 순서

  • 외부 API 호출 시 dependency 순서 고려
  • Circuit breaker 패턴 적용

Redis/메모리 캐시

  • 여러 키를 동시에 락할 때 알파벳 순서로 정렬

✨ 꿀팁

  1. 항상 같은 순서: 자원 접근 순서를 정해두기
  2. 타임아웃 필수: 무한 대기 방지
  3. 최소한의 락: 꼭 필요한 부분만 락 걸기
  4. 빠른 해제: 작업 완료 즉시 자원 해제

🎉 마무리

교착상태는 멀티스레딩 환경에서 피할 수 없는 문제지만, 올바른 설계와 패턴으로 충분히 예방할 수 있어요!

특히 Next.js API Routes나 Node.js 서버에서 동시성 처리할 때 항상 염두에 두시길 바라요 🚀

 


교착 상태에 대해서 설명해주세요.

백엔드와 관련된 질문이에요.

교착 상태(deadlock) 는 두 개 이상의 작업이 서로 상대방의 작업이 끝나기만을 기다리고 있어 결과적으로 아무것도 완료되지 못하는 상태를 의미합니다. 가령, A 프로세스가 자원 A를 가지고 자원 B를 필요로 합니다. 그리고, B 프로세스는 자원 B를 가지고 자원 A가 필요할 때 두 개의 프로세스는 교착 상태에 빠져 어느 작업도 진행할 수 없는 상황이 됩니다.

교착 상태가 발생하는 조건을 알고 계신가요? 🤔

4가지 조건(상호 배제, 점유 대기, 비선점, 원형 대기)이 모두 만족하는 경우, 교착 상태에 빠질 수 있습니다.

  • 상호 배제(mutual exclusion) 는 한 프로세스가 사용하는 자원을 다른 프로세스가 사용할 수 없는 경우를 의미합니다.
  • 점유 대기(hold and wait) 는 자원을 할당받은 상태에서 다른 자원을 할당받기를 기다리는 상태를 의미합니다.
  • 비선점(non-preemption) 은 자원이 강제적으로 해제될 수 없으며 점유하고 있는 프로세스의 작업이 끝난 이후에만 해제되는 것을 의미합니다.
  • 원형 대기(circular wait) 은 프로세스들이 원의 형태로 자원을 대기하는 것을 의미합니다.

자바에서 교착 상태는 어떻게 해결할 수 있나요? 😀

// thread 1
synchronized (resource1) { 
  synchronized(resource2) { ... }
}

// thread 2
synchronized (resource2) { 
  synchronized(resource1) { ... }
}

예를 들어, 자바의 syncronized 키워드로 인한 교착 상태가 발생했다고 가정해보겠습니다. 위와 같은 경우에는 외부 synchronized 블록 내부에 synchronized 블록을 포함하지 않도록 개선하여 점유 대기 조건을 제거하여 교착 상태를 해결할 수 있습니다.

이외에도 ReentrantLock을 사용하는 경우에는 tryLock() 메서드를 사용하여 타임아웃을 설정하거나, lockInterruptibly() 메서드를 사용하여 데드락이 발생하는 경우, 인터럽트를 통해 스레드를 깨울 수 있습니다.

정리하자면 교착 상태가 발생하는 4가지 조건 중 하나를 충족하지 못하게 하거나, 대기하는 경우 무한정 기다리지 않는 방식으로 교착 상태를 풀어볼 수 있습니다.

728x90