강의 메모 - sleep() #
개요 #
- 지정된 시간 동안 현재 스레드의 실행을 일시 정지하고 대기상태로 빠졌다가 시간이 지나면 실행대기 상태로 전환된다
- native 메서드로 연결되며 시스템 콜을 통해 커널모드에서 수행 후 유저모드로 전환한다
- 이 간단한 메서드 자체도 jvm 자체에서 실행되지 못하고 커널모드에서 수행된다.
- 컨텍스트 스위칭 발생
API 및 예외 #
staic sleep(long millis) throws InterruptedException #
지정한 밀리초 시간 동안 스레드를 수면 상태로 만든다 밀리초에 대한 인수 값은 음수가 될 수 없으며 음수 일 경우 IllegalArgumentException 이 발생한다
static sleep( long millis, int nanos) InterruptedException #
지정한 밀리초에 나노초를 더한 시간 동안 스레드를 수면 상태로 만든다, 나노초의 범위는 0 에서 999999 이다
InterruptedException #
스레드가 수면 중에 인터럽트(쓰레드 실행의 중단의 신호를 보냄) 될 경우 InterruptedException 예외를 발생시킨다 sleep() 메서드 사용시, try~catch로 InturrptedException 예외처리가 필요하다. 다른 스레드는 잠자고 있는 스레드에게 인터럽트, 즉 중단(멈춤) 신호를 보낼 수 있다 InterruptedException 예외가 발생하면 스레드는 수면상태에서 깨어나고 실행대기 상태로 전환되어 실행상태를 기다린다 -> sleep()에서 깨어나는 조건 : 예외 발생 (실행대기 상태로 전환, 다시 실행상태로 전환가능한 상태)
예시) 쓰레드 T1, 쓰레드 T2 쓰레드 T1이 sleep() 메서드를 만나서 3초 대기를 하다가, T2가 T1에 인터럽트를 걸면 3초가 지나지않아도 catch문으로 이동된다. 또한 인터럽트를 건 이후, sleep() 메서드를 만나면 바로 catch문으로 이동된다.
Sleep() 작동 방식 #
지정된 시간이 지난 경우 #
interrupt() 발생할 경우 #
Sleep(0)과 Sleep(n)의 의미 #
- sleep(millis) 메서드는 네이티브 메서드이기 때문에 sleep(millis) 을 실행하게 되면 시스템 콜을 호출하게 되어 유저모드에서 커널모드로 전환된다
- 다른 스레드에게 명확하게 실행을 양보하기 위함이라면 sleep(0) 보다는 sleep(1) 을 사용하도록 한다
- sleep(0)은 아래 내용과 같이 조건에 따라서 양보할수도 있고, 그대로 실행될수도 있기 때문이다.
sleep(0) #
- 스레드가 커널 모드로 전환 후 스케줄러는 현재 스레드와 동일한 우선순위(Priority)의 스레드가 있을 경우 실행대기상태 스레드에게 CPU 를 할당함으로 컨텍스트 스위칭이 발생한다
- 기본적으로 sleep()은 컨텍스트 스위칭이 발생하는데, sleep(0)은 조건이 있어야 컨텍스트 스위칭이 발생한다.
- 조건 : 현재 스레드와 동일한 우선순위의 스레드가 있을 경우 (Runnable 상태인 스레드여야함)
- 만약 우선순위가 동일한 실행대기 상태의 다른 스레드가 없으면 스케줄러는 현재 스레드에게 계속 CPU 를 할당해서 컨텍스트 스위칭이 없고 모드 전환만 일어난다
- sleep()은 커널모드로 왔으므로, 다시 유저모드로 전환만 발생한다는 뜻이다.
- 기본적으로 sleep()은 컨텍스트 스위칭이 발생하는데, sleep(0)은 조건이 있어야 컨텍스트 스위칭이 발생한다.
- user -> kernel
- kernel -> user
sleep(n) #
- 스레드가 커널 모드로 전환 후 스케줄러는 조건에 상관없이 현재 스레드를 대기상태에 두고 다른 스레드에게 CPU 를 할당함으로 모든 전환과 함께 컨텍스트 스위칭이 발생한다
sleep() 작동 방식 원리 #
- sleep() 이 되면 OS 스케줄러는 현재 스레드를 지정된 시간 동안 대기 상태로 전환하고 다른 스레드 혹은 프로세스에게 CPU 를 사용하도록 한다
- 대기 시간이 끝나면 스레드 상태는 바로 실행상태가 아닌 실행 대기 상태로 전환 되고 CPU 가 실행을 재개할 때 까지 기다린다.
- 쓰레드가 sleep() 상태에서 깨어난다고 해서 바로 실행되는게 아닌 실행대기 상태로 전환되고 실행되는 것이다.
- 실행 상태가 되면 스레드는 남은 지점부터 실행을 다시 시작한다
- 동기화 메서드 영역에서 수면 중인 스레드는 획득한 모니터나 락을 잃지 않고 계속 유지한다
- 쓰레드A가 lock을 가지고 있다가 wait(대기)상태로 빠졌을때 lock을 풀어버린다.
- 하지만 sleep()은 lock을 가지고 있다가 sleep()을 만나게 되더라도 lock을 풀지 않는다. 계속 유지한다.
- sleep() 중인 스레드에게 인터럽트가 발생할 경우 현재 스레드는 대기에서 해제되고 실행상태로 전환되어 예외를 처리하게 된다
- try~catch에서 catch()문 실행
- 스레드의 수면 시간은 OS 스케줄러 및 시스템 기능에 따라 제한되기 때문에 정확성이 보장되지 않으며 시스템의 부하가 많고 적음에 따라 지정한 수면 시간과 차이가 날 수 있다
- sleep(3000)일때 2.9초일수도, 3초일수도 있다. 시스템 부하에 따라 조금씩 차이가 날 수 있다.