프로세스/스레드의 OS Level에서의 State
맨 처음, new로 인해서 프로세스/스레드가 생성이 되어, cpu에 의해 실행될 준비(ready)를 한다.
new에서 ready state로 넘어 갈 때, Long term Scheduler의 허락을 받아야 한다.
그러나 Long term scheduler는 RealTime OS와 같은 특별한 OS에서만 동작을 하고,
보통의 우리가 사용하는 OS에서는 Long Term Scheduler 없이, 바로 new에서 ready로 넘어 간다고 생각해보 무방하다.
ready state에 있는 프로세스/스레드는 큐에 대기해 있다가, CPU에서 실행 중인 프로세스/스레드가 time slice를 다 썼거나
, critical section에 진입하기 위하여 대기하게 위하여 또는 I/O 작업등으로 CPU 사용을 더 이상 하지 않을 때, 큐에서 CPU
로 꺼내져 running state가 된다.
이때, CPU에서 실행이 되다가 모종의 이유로 또 CPU 사용을 하지 않게 되면, ready state로 다시 돌아가거나, terminated
state 또는 waiting state로 변경이 된다.
(사실은, 위 과정보다 실제로는 더 복잡하나, 이렇게 이해를 해도 문서를 봐도 무리없이 이해가 가능하다.)
(위 state의 용어는 OS마다 다를 수가 있다.)
JAVA 프로그래밍 언어 Level에서의 Thread의 state
JAVA Thread의 state에는 아래 6가지가 있다.(참고로, 프로그래밍 언어마다 Thread의 state가 다를 수 있다.)
1.NEW : JAVA Thread가 아직 시작하지 않은 상태
2.RUNNABLE : 실행 중인 상태 AND 다른 리소스를 기다리는 상태
-> CPU(리소스)에서 실행되려고 기다리는 상태도 RUNNABLE 상태가 된다.
-> I/0 작업이 끝나서 결과값(리소스)을 기다리는 상태도 RUNNABLE 상태가 된다.
3.BLOCKED : 모니터 lock을 얻기 위해 기다리는 상태.(= critical section으로 들어가려고 모니터 lock을 얻기 위해 기다리는 상태)
4.WAITING : 다른 스레드를 기다리는 상태
java에서는 대표적으로 WAITING State를 위한 메서드가 2개가 있다.
a) Object :: wait() // 모니터 관련된 wait
b) Thread :: join()
etc....
5.TIMED_WAITING : 제한 시간을 두고 다른 스레드를 기다리는 상태.
java에서는 대표적으로 TIMED_WAITING State를 위한 메서드가 3개가 있다.
a) Object :: wait(timeout)
b) Thread :: join(timeout)
c) Thread :: sleep()
etc...
6.TERMINATED : 실행을 마치고 종료된 상태
위 코드는 이전 시간 모니터에서 사용되었던 예제이다.
이 예제를 통하여 2개의 JAVA Thread인, consumer 스레드, producer 스레드의 state의 변환를 확인할 것이다.
( synchronized 메서드 or synchronized block에는 한 번에 한 개의 Thread만 진입을 할 수가 있고,
이 부분에 진입을 하는 Thread 인스턴스는 모니터(=뮤텍스)를 쥐고 진입을 하게 된다.)
1. new BoundedBuffer()에 의해 객체가 생성됨과 동시에 이 객체 고유의 모니터를 가진다.
2. new Thread()를 통해, consumer , producer 스레드가 생성이 되고, start()에 의해 2개의 스레드가 실행됨.
3. consumer, producer 스레드가 처음 만들어 지면, state는 new state가 된다.
4. consumer.start()가 실행이 되면 RUNNABLE State로 바뀜.
5. consume() 내의 synchronized(this), 즉 synchronized(BoundedBuffer객체)에 의해 consumer 스레드가 모니터 lock을
획득할 수 있는지 확인하고, 가능하다면 모니터를 쥔 채로 critical section으로 진입을 한다.
6. 그러나 BoundedBuffer :: buffer 변수 안에는 아직 아무런 item이 들어 있지 않기에 , wait() 메서드가 호출이 되며,
consumer 스레드는 가지고 있던 모니터 lock을 반환하고 WAITING State로 바뀌게 된다.
7. producer 스레드가 실행이 된다.( producer 스레드의 state는 여기서는 언급하지 않겠다.)
8. ciritical section에 진입하기 위해서 반화된 모니터 lock을 쥐고 진입을 한다.
9. 100개의 item을 삽입하고 notifyAll()로 인해 CV에 잠들어 있는 consumer thread를 깨운다.
여기서 주의해야 할 것이 있다. consumer thread가 깨어난다고 해서 바로 Runnable State로 바뀌는 것이 아니다.
JAVA는 기본적으로 Signal and Continue여서 producer 스레드가 consumer 스레드를 깨워도 critical section을 전부 실행
을 할 때까지는 모니터 lock을 반환하지 않기 때문에 consumer 스레드는 모니터 lock을 기다리기 위하여 BLOCKED State
가 된다.
(signal-and-continue: P signals Q and then Q waits until P leaves the monitor)
10. produer 스레드는 모니터 lock을 쥔 상태로 나머지 ciritical sectino 코드를 실행해 나가고, produce() 실행이 완료되면
모니터 lock을 반환하므로, consumer 스레드는 다시 Runnable State로 바뀌게 된다.
11. consumer 스레드도 consume() 실행을 완려하면 TERMINATED 상태가 된다.
Thread Dump
실행 중인 JAVA 프로세스/스레드의 현재 상태를 담은 SnapShot
-> Thread Dump를 이용하여 서비스에 문제가 터졌을 때 어디가 문제인지 정확하게 진단을 할 수가 있다.
'CS 과목(CS科目) > 운영체제(OS)' 카테고리의 다른 글
인터럽트(interrupt), 시스템 콜(System Call), 유저 모드(user mode), 커널 모드(kernel mode) (2) | 2022.12.31 |
---|---|
CPU 스케줄러, Dispatcher (1) | 2022.12.30 |
dead lock(교착상태) with JAVA (0) | 2022.12.27 |
모니터(monitor)(sub: 그 모니터 아닙니다 ㅋㅋ) (0) | 2022.12.23 |
스핀락(spinlock) 뮤텍스(mutex) 세마포(semaphore) (0) | 2022.12.23 |