START HERE
30초 핵심
CPU 사용률만 보지 말고 프로세스 상태와 자원 점유·해제 흐름을 함께 본다.
데드락은 자원을 가진 채 서로 기다려 Blocked / Waiting으로 멈춘 상태이고, 라이브락은 양보·재시도를 반복하며 Running 중이지만 실제 진전이 없는 상태다.
QUESTION → CHANGE → EXPLANATION
두 프로세스는 자원을 기다리는가, 아니면 다시 시도하는가?
자원 1과 자원 2를 두 프로세스가 나누어 쓰는 상황을 한 단계씩 관찰한다. 각 카드에서 상태와 자원 목록을 함께 읽어 보자.
- 질문자원 때문에 멈춘 것인가?
- 조작다음 단계·자동 재생을 눌러 본다.
- 변화점유·대기·해제를 비교한다.
- 해설상태·CPU·진전을 따로 판단한다.
자동 재생은 흐름을 보여 주고, 일시정지는 한 단계의 자원 상태를 읽을 시간을 준다.
자원 충돌 시뮬레이션
같은 출발점에서 데드락과 라이브락이 어떻게 갈라지는지 비교한다.
현재 단계를 확인해 보세요.
다음 단계를 눌러 상태와 자원 흐름의 차이를 관찰해 보세요.
-
하나씩 먼저 얻는다
데드락으로 이어질 수 있는 흐름
아직 멈추지는 않았지만, 각자 가진 자원을 놓지 않는 선택이 시작됐다.
프로세스 P1
Running- 자원 1 · 점유
- 자원 2 · 필요
프로세스 P2
Running- 자원 2 · 점유
- 자원 1 · 필요
라이브락으로 이어질 수 있는 흐름
같은 출발점이다. 다음 단계에서 실패하면 잠금을 놓고 다시 시도하는 규칙을 사용한다.
프로세스 P1
Running- 자원 1 · 점유
- 자원 2 · tryLock
프로세스 P2
Running- 자원 2 · 점유
- 자원 1 · tryLock
-
두 번째 자원에서 충돌한다
데드락 · 서로의 자원을 기다림
잠금을 기다리므로 두 프로세스의 실행 흐름이 멈춘다.
프로세스 P1
Blocked / Waiting- 자원 1 · 계속 점유
- 자원 2 · P2가 점유
프로세스 P2
Blocked / Waiting- 자원 2 · 계속 점유
- 자원 1 · P1이 점유
상태대기 조건이 풀리지 않음CPU해당 스레드는 낮은 편라이브락 · 서로의 자원을 양보함
두 번째 잠금을 기다리지 않고 첫 번째 잠금을 놓을 준비를 한다.
프로세스 P1
Running- 자원 1 · 곧 해제
- 자원 2 · 획득 실패
프로세스 P2
Running- 자원 2 · 곧 해제
- 자원 1 · 획득 실패
상태실패 처리와 재시도 실행CPU바쁜 재시도라면 높을 수 있음 -
시간이 지나도 진전이 없다
데드락 · 멈춰 있는 고리
자원 1과 2의 점유자가 바뀌지 않아 대기 고리가 유지된다.
프로세스 P1
Blocked / Waiting- 자원 1 · 점유 유지
- 자원 2 · 계속 대기
프로세스 P2
Blocked / Waiting- 자원 2 · 점유 유지
- 자원 1 · 계속 대기
진전작업 완료 0건관찰대기 관계가 변하지 않음라이브락 · 움직이는 고리
둘 다 해제하고, 같은 타이밍에 같은 패턴으로 다시 자원을 잡는다.
프로세스 P1
Running- 자원 1 · 해제
- 자원 1 · 재획득 시도
프로세스 P2
Running- 자원 2 · 해제
- 자원 2 · 재획득 시도
진전작업 완료 0건관찰해제·재획득 로그는 계속 생김 -
해결 규칙을 넣어 진전을 만든다
데드락 해결 · 대기 고리를 끊기
모든 작업이 자원 1 → 자원 2 순서로만 잠그면 서로 반대 순서로 기다릴 수 없다.
프로세스 P1
Running- 자원 1 → 자원 2
- 작업 후 모두 해제
프로세스 P2
Ready- 같은 순서로 대기
- P1 후 실행
라이브락 해결 · 재시도 타이밍 바꾸기
실패한 작업이 서로 다른 시간만큼 쉬면 다음 시도가 겹치지 않을 가능성이 커진다.
프로세스 P1
Running- 자원 1·2 · 획득
- 작업 완료
프로세스 P2
Ready- Random Backoff
- 다음 차례에 성공
- 자원 점유·필요
- 대기·충돌
- 해제·진전
TWO AXES
상태와 자원, 두 축으로 구분하기
“멈췄다”와 “계속 움직인다”는 표현을 프로세스 상태와 자원 관계로 번역하면 두 문제가 선명해진다.
데드락 · Deadlock
프로세스들이 자원을 점유한 채 서로가 가진 자원을 기다린다. 잠금이 풀릴 조건이 사라져 Blocked / Waiting 상태에서 깨어나지 못한다.
라이브락 · Livelock
프로세스들이 충돌을 피하려고 자원을 놓고 다시 시도한다. Running 동작은 이어지지만 유용한 작업의 완료라는 진전은 없다.
| 관찰 기준 | 데드락 | 라이브락 |
|---|---|---|
| 프로세스 상태 | Blocked / Waiting | Running 또는 실행 가능한 Ready |
| 자원 흐름 | 하나를 가진 채 다른 자원을 기다림 | 얻었다가 놓고 다시 얻기를 반복 |
| CPU 단서 | 해당 대기 스레드는 낮은 편 | 바쁜 재시도라면 높은 편 |
| 진전 | 대기 관계가 고정되어 없음 | 상태 변화는 있지만 실제 완료는 없음 |
판단 순서: 현재 상태 → 누가 어떤 자원을 점유했는가 → 다음 행동은 대기인가 재시도인가 → 실제 작업이 완료되었는가.
STOPPED
데드락: 자원을 가진 채 서로 기다린다
골목길에서 두 차가 마주 보고 멈춘 것처럼, 각 프로세스가 양보하지 않고 상대방의 자원을 기다리는 상태다.
자원 B를 기다림
자원 A를 기다림
-- 설명용 의사 SQL: WAIT는 특정 DBMS의 표준 문법이 아님
-- Transaction A
BEGIN;
UPDATE table_a SET value = value + 1 WHERE id = 1; -- 자원 A 잠금
UPDATE table_b SET value = value + 1 WHERE id = 1; -- 자원 B 대기
-- Transaction B
BEGIN;
UPDATE table_b SET value = value + 1 WHERE id = 1; -- 자원 B 잠금
UPDATE table_a SET value = value + 1 WHERE id = 1; -- 자원 A 대기
DBMS가 뭐예요?
DBMS(Database Management System)는 데이터를 저장·검색·수정하고, 트랜잭션과 잠금 같은 동시 접근 규칙을 관리하는 소프트웨어다. PostgreSQL·MySQL·Oracle Database가 예다.
발생하면 어떻게 하나요?
많은 DBMS는 대기 관계를 감지해 한 트랜잭션을 취소하거나 롤백한다. 그래도 애플리케이션은 취소된 작업을 재시도할지, 오류를 어떻게 보여 줄지 결정해야 한다.
BUSY BUT NO PROGRESS
라이브락: 계속 움직이지만 앞으로 가지 못한다
복도에서 서로 비켜 주려다 같은 방향으로 움직이는 것처럼, 실패 처리와 재시도가 계속되지만 실제 작업은 끝나지 않는다.
function work(first, second) {
while (true) {
if (!tryLock(first)) continue; // 기다리지 않고 바로 실패
if (!tryLock(second)) {
unlock(first); // 먼저 잡은 자원을 양보
continue; // 곧바로 다시 시도
}
doUsefulWork();
unlock(second);
unlock(first);
return;
}
}
// A: work(lock1, lock2)
// B: work(lock2, lock1)
Running 로그나 자원 해제 로그가 생겨도 결과 데이터가 바뀌거나 작업이 완료되지 않으면 진전이 아니다.
tryLock 실패 → 해제 → 즉시 재시도가 같은 타이밍으로 반복되는지 살펴본다.
CPU 주의: 쉬지 않고 재시도하면 CPU 사용이 높을 수 있지만, 재시도 사이에 sleep하거나 CPU를 양보하면 낮을 수도 있다. CPU는 보조 단서다.
DEADLOCK CHECKLIST
데드락의 네 가지 조건 · Coffman Conditions
보통 아래 네 조건이 모두 성립해야 데드락이 가능해진다. 하나를 깨면 데드락을 예방할 여지가 생긴다.
1. 상호 배제
한 번에 한 프로세스만 사용할 수 있는 자원이 있다.
2. 점유하며 대기
이미 가진 자원을 놓지 않은 채 다른 자원을 기다린다.
3. 비선점
다른 프로세스가 자원을 강제로 빼앗을 수 없고, 가진 쪽이 직접 놓아야 한다.
4. 순환 대기
A는 B의 자원을, B는 A의 자원을 기다리는 고리가 생긴다.
예방 아이디어: 모든 작업이 자원 1 → 자원 2처럼 정해진 순서로 잠금을 얻으면 서로 반대 순서로 기다리는 순환 대기를 만들기 어려워진다.
CLASSIC & REAL SYSTEMS
식사하는 철학자와 실제 라이브락
공유 자원을 여러 작업이 나누어 쓰는 상황에서는 데드락과 라이브락이 코드·네트워크·분산 시스템에서 다른 모습으로 나타난다.
식사하는 철학자 문제
철학자 다섯 명이 양옆 포크 두 개를 모두 가져야 식사할 수 있다. 모두 왼쪽 포크를 먼저 집으면 각자 하나씩 가진 채 오른쪽 포크를 기다리므로 데드락이 된다.
각 철학자: 왼쪽 포크 점유 → 오른쪽 포크 대기 결과: 아무도 두 포크를 모두 얻지 못함
실제 라이브락 사례
동시 자료구조의 compare-and-swap 재시도, 잠금 충돌 후 즉시 재시도, 충돌한 네트워크 장치의 동시 재전송, 여러 서비스의 같은 시점 재시도에서 생길 수 있다.
실패 감지 → 즉시 재시도 → 다시 충돌
↖ 같은 타이밍으로 반복 ↙
MAKE PROGRESS
해결 방법은 무엇이 다를까?
데드락은 대기 고리를 끊고, 라이브락은 반복 타이밍과 무한 재시도를 끊는 방향으로 접근한다.
데드락 해결
자원 순서 정렬: 항상 같은 순서로 잠근다.
감지 후 취소: 한 트랜잭션을 롤백해 고리를 끊는다.
타임아웃: 영원히 기다리지 않고 포기한다.
보유 시간 줄이기: 잠금 중 긴 계산·네트워크 요청을 피한다.
라이브락 해결
Random Backoff: 실패 후 임의의 시간만큼 쉰다.
재시도 제한: 무한 while (true)를 막는다.
공정한 순서: 대기열로 다음 차례를 보장한다.
진전 기록: 반복과 성공을 구분한다.
SAY IT YOURSELF
내가 설명해 보기
아래 질문에 답할 때 “상태 → 자원 → 다음 행동 → 진전” 순서를 사용해 보자.
- 데드락과 라이브락의 차이를 프로세스 상태와 자원 흐름으로 설명해 보자.
- A는 자원 1을, B는 자원 2를 가진 채 서로 기다릴 때 왜 데드락인지 말해 보자.
tryLock실패 후 잠금을 놓고 곧바로 재시도하는 코드가 라이브락이 될 수 있는 이유를 설명해 보자.- DBMS가 하는 일을 데이터 저장, 트랜잭션, 잠금 중 두 가지 이상을 사용해 설명해 보자.
- Random Backoff가 라이브락을 줄이는 원리를 “같은 타이밍”과 연결해 설명해 보자.
CHECK YOUR UNDERSTANDING
이해 확인 퀴즈
정답을 보기 전에 먼저 자신의 말로 답해 보자.
- 객관식: 다음 중 데드락에 가장 가까운 상황은 무엇일까?
A. 두 스레드가 실패할 때마다 잠금을 놓고 즉시 다시 시도한다.
B. A는 잠금 1을 가진 채 잠금 2를 기다리고, B는 잠금 2를 가진 채 잠금 1을 기다린다.
C. 한 스레드가 자원을 얻지 못해 한 번 오류를 반환하고 종료한다.
D. 작업이 끝난 뒤 잠금을 해제하고 다음 작업을 시작한다. - 참/거짓: 라이브락은 항상 CPU 사용률이 100%이므로 CPU 사용률만 측정하면 확실히 판별할 수 있다.
- 짧은 설명: DBMS가 무엇이며, 트랜잭션 사이의 데드락을 감지한 뒤 할 수 있는 일을 한 가지 적어 보자.
- 빈칸 채우기: 이미 가진 자원을 놓지 않은 채 다른 자원을 기다리는 Coffman 조건은 무엇일까?
- 상황 판단: 두 작업의 로그에 “lock 1 성공 → lock 2 실패 → lock 1 해제 → 즉시 재시도”가 수천 번 반복된다. 두 작업 모두
Running이고 결과 데이터는 바뀌지 않았다. 무엇에 가까운지와 해결 방법 하나를 적어 보자.
정답과 해설 보기
1. B. 각 스레드가 자원을 하나씩 점유한 채 상대방의 자원을 기다리므로 순환 대기가 생긴다. A는 잠금을 놓고 즉시 다시 시도하므로 라이브락에 가깝다.
2. 거짓. 쉬지 않는 재시도라면 CPU가 높을 수 있지만, 재시도 사이에 잠들거나 CPU를 양보하면 낮을 수도 있다. 프로세스 상태와 자원 흐름을 먼저 봐야 한다.
3. DBMS는 데이터를 저장·검색·수정하고 트랜잭션·잠금 같은 동시 접근 규칙을 관리하는 소프트웨어다. 데드락을 감지하면 한 트랜잭션을 취소·롤백해 대기 고리를 끊을 수 있다.
4. 점유하며 대기(Hold and Wait). 자원을 가진 채 다른 자원을 기다리는 조건이다.
5. 라이브락. 코드가 계속 실행되지만 자원을 얻었다 놓는 행동만 반복하고 실제 결과가 진행되지 않는다. Random Backoff, 재시도 횟수 제한, 공정한 대기열 등을 사용할 수 있다.
TAKEAWAY
한 문장으로 기억하기
데드락은 자원을 가진 채 서로 기다려 멈춘 상태이고, 라이브락은 자원을 양보하며 계속 실행하지만 진전이 없는 상태이므로, CPU보다 프로세스 상태와 자원 점유·해제 흐름을 먼저 보자.