Computer Engineering/Java & Spring
자바의 정석 : 13장 스레드
soohey
2022. 9. 13. 11:43
챕터 13 스레드 Thread를 읽으며 기록해보았습니다 : )
싱글스레드와 멀티스레드
- 하나의 스레드로 두개의 작업을 수행한 시간과 두개의 스레드로 두 개의 작업을 수행한 시간은 같다.
- 두개의 스레드로 작업할 때 싱글스레드보다 더 시간이 걸림 -> 스레드간 작업전환시간이 길어서 (컨텍스트 스위칭)
- 작업 전환시 현재 진행중인 작업의 상태, 다음에 실행해야할 위치 등의 정보를 저장하고 읽는 시간이 소요됨.
- 싱글 코어인 경우 두 작업이 겹치지 않음
- 멀티 스레드 수행시 두 작업이 겹치는 부분이 발생함. 그래서 화면이라는 작원을 놓고 경쟁함
- 두 스레드가 서로 다른 작업 사용시 싱글보다 멀티스레드가 더 효율적임
스레드의 우선순위
- 스레드는 우선순위라는 속성을 가짐(멤버변수)
- 우선순위에 따라 작업시간이 달라짐
- 빠르게 반응해야할수록 우선순위가 높아야 함
- 멀티 코어에서는 우선순위에 따른 차이가 없음
- 우선순위에 차등을 두어 스레드 실행하려면 OS의 스케줄링 정책과 JVM 구현을 직접 확인해보기.
스레드 그룹
- 서로 관련된 스레드를 그룹으로 다룸
- 모든 스레드는 반드시 스레드 그룹에 포함되어 있어야 함
데몬 스레드
- 다른 일반 스레드의 작업을 돕는 보조적인 역할
- 일반 스레드들이 다 종료되면 보조도 종료됨
- ex) 가비지 컬렉터, 워드프로세서의 자동저장, 화면자동갱신
스레드의 실행제어
- 동기화와 스케줄링이 어려움
- 스레드 스케줄링을 잘하려면 스레드 상태와 관련 메서드를 잘 알아야 함.
- 스레드의 생성부터 소멸까지 모든 과정 그리기
- 스레드 생성하고 start()호출시 실행대기열(큐)에 저장되어 대기함
- 자신 차례가 되면 실행상태가 됨
- 주어진 실행시간이 되거나 yield()를 만나면 다시 실행대기상태가 되고 다음 차례 스레드가 실행상태가 됨
- 실행중에 일시정지상태가 될 수 있음 (suspend(), sleep(), wait(), join(), I/O block). 입력을 기다리는 경우일 수 있고, 입력이 마치면 다시 실행대기
- 일시정지시간이 다되면 다시 실행대기열에 저장됨
- 실행을 마치거나 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 키워드 추가시 캐시가 아닌 메인 메모리에 저장하고 읽어오기 때문에 캐시와 메모리간의 변수값 불일치 문제를 해결할 수 있음.
- 멀티스레드환경에서 하나의 스레드만 읽고 쓰기를 하고 나머지 스레드가 읽는 상황에서 가장 최신의 값을 보장함