Computer Engineering/Java & Spring

자바의 정석 : 13장 스레드

soohey 2022. 9. 13. 11:43

챕터 13 스레드 Thread를 읽으며 기록해보았습니다 : )

 

싱글스레드와 멀티스레드

  • 하나의 스레드로 두개의 작업을 수행한 시간과 두개의 스레드로 두 개의 작업을 수행한 시간은 같다.
  • 두개의 스레드로 작업할 때 싱글스레드보다 더 시간이 걸림 -> 스레드간 작업전환시간이 길어서 (컨텍스트 스위칭)
  • 작업 전환시 현재 진행중인 작업의 상태, 다음에 실행해야할 위치 등의 정보를 저장하고 읽는 시간이 소요됨.
  • 싱글 코어인 경우 두 작업이 겹치지 않음
  • 멀티 스레드 수행시 두 작업이 겹치는 부분이 발생함. 그래서 화면이라는 작원을 놓고 경쟁함
  • 두 스레드가 서로 다른 작업 사용시 싱글보다 멀티스레드가 더 효율적임

 

스레드의 우선순위

  • 스레드는 우선순위라는 속성을 가짐(멤버변수)
  • 우선순위에 따라 작업시간이 달라짐
  • 빠르게 반응해야할수록 우선순위가 높아야 함
  • 멀티 코어에서는 우선순위에 따른 차이가 없음
  • 우선순위에 차등을 두어 스레드 실행하려면 OS의 스케줄링 정책과 JVM 구현을 직접 확인해보기.

 

스레드 그룹

  • 서로 관련된 스레드를 그룹으로 다룸
  • 모든 스레드는 반드시 스레드 그룹에 포함되어 있어야 함

 

데몬 스레드

  • 다른 일반 스레드의 작업을 돕는 보조적인 역할
  • 일반 스레드들이 다 종료되면 보조도 종료됨
  • ex) 가비지 컬렉터, 워드프로세서의 자동저장, 화면자동갱신

 

스레드의 실행제어

  • 동기화와 스케줄링이 어려움
  • 스레드 스케줄링을 잘하려면 스레드 상태와 관련 메서드를 잘 알아야 함.
  • 스레드의 생성부터 소멸까지 모든 과정 그리기
  1. 스레드 생성하고 start()호출시 실행대기열(큐)에 저장되어 대기함
  2. 자신 차례가 되면 실행상태가 됨
  3. 주어진 실행시간이 되거나 yield()를 만나면 다시 실행대기상태가 되고 다음 차례 스레드가 실행상태가 됨
  4. 실행중에 일시정지상태가 될 수 있음 (suspend(), sleep(), wait(), join(), I/O block). 입력을 기다리는 경우일 수 있고, 입력이 마치면 다시 실행대기
  5. 일시정지시간이 다되면 다시 실행대기열에 저장됨
  6. 실행을 마치거나 stop()이 호출되면 스레드 소멸

 

sleep() - 일정시간동안 스레드 멈춤

  • sleep 호출시 일시정지 상태가 되고 interrupt 호출시 잠에서 깨어나 실행되기가 됨

 

interrupt(), interrupted() - 스레드의 작업을 취소

  • 진행중인 스레드 작업이 끝나기 전에 취소해야할 경우
  • 요청만 하지 강제 종료는 아님
  • interrupt() 호출시 interrupted()가 false 에서 true가 됨
  • sleep 도중에 InterruptedException이 발생하면 interrupted상태가 false로 자동 초기화 -> catch 블럭에 interrupt 추가하여 true로 바꾸기

suspend(), resume(), stop()

  • suspend : 스레드 멈춤
  • resume : 실행대기 상태
  • stop : 종료
  • 셋다 deprecated됨

yield() - 다른 스레드에게 양보한다.

  • suspended가 true인 상태로 반복문을 돌면 while을 의미없이 도는 낭비상태가 됨 ( busy-waiting)
  • yeild를 호출해서 남은 실행시간을 낭비하지 않고 다른 스레드에게 양보하여 효율적
  • interrupt를 호출하면 InterruptedException이 발생하여 즉시 일시정지 상태에서 벗어나므로 응답성이 높아짐. 

join - 다른 스레드의 작업을 기다림

  • join을 사용하지 않았으면 메인 스레드는 바로 종료되었겠지만, join으로 스레드 th1과 th2의 작업을 마칠 때까지 메인스레드가 기다리도록 했다.

스레드의 동기화

  • 멀티스레드의 경우 여러스레드가 같은 프로세스 내의 자원을 공유하기 때문에 서로의 작업에 영향을 준다.
  • 이를 방지하기 위해 한 스레드가 작업사용시 다른 스렏가 접근하지 못하도록 제어함. -> 잠금, 임의영역
  • 임의영역에 락을 획득한 하나의 스레드만 코드를 수행하도록 함. 

1. synchronization

  • private설정으로 외부 접근을 막아야함

2. wait(), notify()

  • 특정 스레드가 락을 가진 상태로 오래가지 않도록 관리 필요
  • wait 호출시 실행중이던 스레드는 대기실에서(waiting pool) 에서 통지를 기다림
  • notify 호출시 대기 스레드 중 임의의 스레드만 통지를 받음
  • 기아 현상 : 스레드가 계속 통지를 받지 못하고 기다리는 상태, notifyall()사용
  • 경쟁상태 : 여러 스레드가 lock을 얻기위해 서로 경쟁 -> 요리사와 손님 스레드를 구별해서 통지해야함

3. Lock과 Condition을 이용한 동기화

 

volatile

  • 멀티 스레딩 환경에서 동기화를 해주는 키워드
  • Volatile 키워드 추가시 캐시가 아닌 메인 메모리에 저장하고 읽어오기 때문에 캐시와 메모리간의 변수값 불일치 문제를 해결할 수 있음.
  • 멀티스레드환경에서 하나의 스레드만 읽고 쓰기를 하고 나머지 스레드가 읽는 상황에서 가장 최신의 값을 보장함