출처: https://www.youtube.com/watch?v=_dzRW48NB9M
서버 불능 시 문제 분석 및 원인 파악에 필수적이기 때문입니다.
| 구분 | OS 프로세스 | 자바 스레드 |
|---|---|---|
| 주요 상태 | New, Ready, Running, Waiting, Terminated | New, Runnable, Blocked, Waiting, Timed Waiting, Terminated |
| Runnable 포함 범위 | Running, Ready | Running, Ready, I/O 대기 등 포괄적 |
원본 자료(OS 프로세스 상태 및 자바스레드 상태)를 100% 이해하기 위해, 영상에서 자세히 다루지 않았지만 핵심적인 맥락과 용어를 깊이 있게 살펴보겠습니다. 특히, 강의를 제공하는 이의 전문성부터 시작해 자바 동시성 제어의 근간이 되는 개념들, 그리고 실제 서버 장애 분석 기법까지 명확하게 이해하는 것이 목표입니다.
원본 자료에서 OS 프로세스 상태와 자바스레드 상태를 비교할 때, 자바의 RUNNABLE 상태가 OS의 Ready와 Running 상태를 모두 포괄하는 매우 광범위한 개념이라고 설명했습니다. 이 차이는 자바가상 머신(JVM)의 작동 방식에서 비롯됩니다.
OS 프로세스의 생애 주기는 비교적 명확하게 구분됩니다.

자바는 java.lang.Thread.State라는 6가지 상태를 정의합니다. 이 중 RUNNABLE 상태는 OS의 스케줄링 영역에 개입하지 않기 위해 Ready와 Running을 하나로 합친 개념입니다.

RUNNABLE의 의미: 스레드가 현재 CPU에서 실행 중이거나, 실행될 준비가 되어 스케줄러의 선택을 기다리고 있는 상태를 모두 포함합니다 .RUNNABLE 상태는 OS의 Ready와 Running 모두에 해당하며, 자바 프로그램 코드 레벨에서는 이 둘을 구별할 수 없습니다.| OS 상태 | Java 상태 | 설명 |
|---|---|---|
| Ready + Running | RUNNABLE | CPU를 얻을 자격이 있으며, 현재 실행 중이거나(Running) 스케줄러의 선택을 기다리는 상태(Ready) |
| Waiting | WAITING | 무한정으로 다른 스레드의 특정 알림을 기다리는 상태 (wait() 호출) |
| I/O Wait, Lock Wait | BLOCKED | 모니터 락(Monitor Lock)을 얻기 위해 대기하는 상태 |
원본 자료에서 자바스레드 상태 중 BLOCKED와 WAITING 상태를 설명할 때 모니터 락(Monitor Lock)과 wait() 메서드가 핵심적으로 언급됩니다. 자바의 동기화가 이루어지는 바탕인 모니터 개념을 명확히 이해해야 합니다.

synchronized 키워드는 바로 이 모니터 메커니즘을 사용합니다 .BLOCKED 상태: 스레드가 synchronized 블록(크리티컬 섹션)에 진입하려 할 때, 이미 다른 스레드가 모니터 락(뮤텍스)을 쥐고 있다면, 이 스레드는 락을 얻기 위해 대기하며 BLOCKED 상태로 바뀝니다 .WAITING 상태: 스레드가 임계 구역 안에서 wait() 메서드를 호출하면, 본인이 쥐고 있던 모니터 락을 스스로 반환하고, 조건 변수가 충족될 때까지(즉, 다른 스레드의 notify() 또는 notifyAll() 호출을 기다리며) WAITING 상태로 빠집니다 .원본 자료의 말미에서 '서버가 불능에 빠졌을 때' 분석 도구로 자바쓰레드 덤프가 언급됩니다. 이는 멀티스레딩 환경에서 발생한 문제를 진단하는 핵심 방법론입니다.

쓰레드 덤프 분석의 핵심은 오랫동안 대기하거나 블록된 스레드를 찾는 것입니다.
BLOCKED나 WAITING 상태로 특정 락을 기다리는 패턴을 통해 데드락을 식별할 수 있습니다 .RUNNABLE스레드에 집중하여, 어떤 코드 블록이 장시간 CPU를 점유하고 있는지 확인합니다.BLOCKED스레드를 확인하여, 어떤 락(Lock) 때문에 작업이 지연되고 있는지 파악합니다.효율적인 문제 진단을 위해 단일 스냅샷이 아닌, 10초 간격으로 최소 3개 이상의 덤프를 연속적으로 수집하여 스레드의 상태 변화 추이를 비교하는 것이 일반적인 권장 사항입니다 .

jps 명령어로 자바프로세스 ID(PID)를 확인하고, jstack -l [PID] > dump.txt 명령어를 사용하여 덤프 파일을 생성할 수 있습니다.![]()
![]()
![]()
Terminate (종료) 상태로의 전이:
스레드 상태와의 관계:
용어의 차이:
| OS 프로세스 상태 | 역할 (비유) | 다음 예상되는 상태 |
|---|---|---|
| New | 새로 태어남 (선수 등록) | Ready |
| Ready | CPU 사용을 대기 (트랙 밖 대기) | Running |
| Running | CPU 사용 중 (트랙 위 달리기) | Ready, Waiting, Terminate |
| Waiting | 외부 자원/I/O 대기 (화장실 사용 대기) | Ready |
| Terminate | 종료됨 (경기 끝) | - |
![]()
자바 스레드의 상태는 운영체제의 프로세스 상태 관리 방식과 다를 수 있으며, 특히 백엔드 자바는 멀티 스레딩 환경에서 많이 구현되므로 자바 스레드 상태를 이해하는 것이 중요하다.
Object 클래스의 wait() 메서드 호출: Object 클래스는 모든 클래스의 조상이며, 인스턴스마다 모니터(뮤텍스 락과 컨디션 변수)를 가지고 있는데, 이 wait() 메서드를 호출하면 스레드는 'WAITING' 상태로 빠진다. Thread 클래스의 join() 메서드 호출: 이 메서드를 호출하게 되면 해당 스레드들은 'WAITING' 상태로 바뀌게 된다. Object 클래스의 wait() 메서드 호출 시 타임아웃(제한 시간)을 파라미터로 전달하는 경우Thread 클래스의 join() 메서드 호출 시 타임아웃 파라미터를 전달하는 경우Thread 클래스의 sleep() 메서드를 호출하는 경우![]()
BoundedBuffer 클래스(버퍼)와 이를 활용하는 Main 클래스 코드를 사용한다. BoundedBuffer 클래스에는 synchronized 키워드가 붙은 produce 메서드와 consume 메서드가 있다. synchronized 키워드가 붙은 메서드나 블록은 한 번에 하나의 스레드만 실행될 수 있으며, 해당 스레드는 객체가 가진 모니터(뮤텍스 락)를 쥐고 들어간다. synchronized로 보호받는 부분은 크리티컬 섹션이다. BoundedBuffer 타입의 인스턴스를 생성하면, 이 객체는 내부적으로 모니터 락과 컨디션 변수를 가진 모니터를 소유하게 된다. Consumer 스레드와 아이템을 밀어 넣는 Producer 스레드 2개를 정의하고 동시에 실행한다. Consumer 스레드가 처음 만들어지면 상태는 NEW이다. start()를 통해 실행을 시작하면 상태는 RUNNABLE이 된다. Consumer 스레드는 consume 메서드를 실행하며 synchronized 블록(크리티컬 섹션)으로 진입을 시도한다. wait() 메서드를 호출한다. wait() 호출 순간, Consumer 스레드의 상태는 WAITING이 되며, 누군가 깨워줄 때까지 잠든다. wait()를 호출하는 순간, Consumer 스레드는 본인이 쥐고 있던 모니터 락을 반환한다. ![]()
Producer 스레드가 시작하여 produce 메서드를 호출한다. Consumer가 락을 반환했기 때문에, Producer는 모니터 락을 성공적으로 확보하고 produce 메서드 안으로 진입한다. Producer는 버퍼가 다 차지 않았으므로 아이템(100)을 버퍼에 채워 넣는다. notifyAll()을 호출하여 잠들고 있던 Consumer 스레드를 깨운다. Consumer 스레드는 깨어나지만, 바로 실행 상태가 되는 것이 아니다. Producer는 notifyAll()을 호출한 후에도 크리티컬 섹션 안에서 모니터 락을 유지하고 계속 활동한다. Consumer 스레드 입장에서는 깨어났지만, 아직 모니터 락을 쥐고 있지 않은 상태이다. Consumer의 상태는 WAITING에서 BLOCKED 상태로 바뀌게 된다. (준비 상태(RUNNABLE)로 바뀌는 것이 아님) ![]()
Producer 스레드는 실행을 마치고 produce 메서드를 탈출하며 쥐고 있던 모니터 락을 반환한다. Consumer 스레드가 이어서 시작할 수 있게 된다. Consumer 스레드의 상태는 RUNNABLE로 바뀌게 된다. Consumer는 깨어났기 때문에 버퍼에서 아이템(100)을 가지고 오고, 혹시 다른 스레드가 기다릴까 싶어 다시 깨우는(notify) 작업을 한 뒤 synchronized 블록을 탈출한다. Consumer는 synchronized 블록을 빠져나온 뒤 컨슈머 메서드를 종료한다. Consumer 스레드의 상태는 최종적으로 TERMINATED가 된다. 
| 자바 스레드 상태 | OS 프로세스 상태와 비슷한 의미 | 설명 |
|---|---|---|
| NEW | New | 스레드가 아직 시작되지 않은 상태예요 . |
| RUNNABLE | Ready + Running | 실행 중이거나 실행 대기 중인 상태를 모두 포괄해요 . |
| BLOCKED | Waiting (일부) | 모니터 락을 얻으려고 기다리는 상태예요 . |
| WAITING | Waiting (무기한) | 다른 스레드를 무기한 기다리는 상태예요 . |
| TIMED_WAITING | Waiting (시간 제한) | 제한 시간을 두고 다른 스레드를 기다리는 상태예요 . |
| TERMINATED | Terminated | 실행을 마치고 종료된 상태예요 . |
![]()