어떤 커뮤니티 보다가 JVM에서 쓰레드 질문이 나옴
다들 쓰레드 생성 비용이 크다고 하고 그래서 쓰레드 풀을 쓴다고 하니 알겠는데
대체 자바에서 쓰레드 생성 비용이 얼마나 되길래 그런걸까?
쓰레드 생성 비용이 비싸다면 언제부터 쓰레드 풀이 효율적인걸까?
사실 쓰레드도 별도의 영역을 가지고 있다.
나는 쓰레드를 단순히 하나의 실행 흐름이라고만 하는게 이상하다고 생각했는데, 쓰레드는 실행흐름을 포함하는거지 쓰레드 자체도 레지스터와 스택을 가진다.
그래서 앞선 컨텍스트 스위칭글 처럼 쓰레드도 컨텍스트 스위칭을 가지고, 이로 인해서 쓰레드의 생성도 메모리의 할당이라는 비용때문에 수 많은 쓰레드가 생성되길 원하지 않는다.
이런 쓰레드 비용에서 작업 요청이 갑자기 1천개가 들어온다면..?
쓰레드 메모리 비용 코드
쓰레드 풀(Thread Pool)은 말 그대로 쓰레드의 모음이다.
제한된 리소스를 이용하여 최대한의 효율을 내기 위한 최적화 기법이랄까
특히, Bottle Neck 현상이 발생하는 I/O 작업과 데이터베이스 작업이 주로 해당된다.
결국 천 개의 쓰레드가 아무리 빠르게 생성되더라도 시스템 스케쥴러에 의해 쓰레드의 우선순위를 매번 할당해야한다.
이것만 보면 쓰레드 풀을 사용하는게 정말정말 효율적인 작업인 것 같다
이렇게 효율적인 쓰레드 풀을 사용했는데 쓰레드 1,2,3에 나누어 배분된 작업 1, 2, 3 중 작업 1이 가장 먼저 끝났을 경우에는 어떻게 될까?
리소스를 효율적으로 사용하려고 최적화 했는데 리소스가 놀다니
이런 일을 눈뜨고 지켜볼 수가 없다
기존 쓰레드 풀을 개선하기 위한 방법으로 Java 7 이상의 쓰레드 풀에서 사용되고있다.
동작은 다음과 같다
1. 작업을 하나의 큰 작업들로써 제공해준다
2. 첫 쓰레드가 작업을 가져와 자신의 로컬 큐에 할당, 분할한다.
3. 두번째 쓰레드가 가져올 작업이 없다면, 첫 쓰레드의 큐에 있는 분할된 작업을 훔쳐간다
4. 나머지 쓰레드도 반복
이렇게 되면 100개의 작업일 때 3개의 쓰레드가 있다면 대략 50, 25, 25 정도의 작업이 수행된다
암달의 법칙은 이렇다. “멀티코어를 사용하는 프로그램의 속도는 프로그램 내부에 존재하는 순차적sequential 부분이 사용하는 시간에 의해서 제한된다.” Thread나 Task를 만들어서 ExecutorService에게 제출하는 식으로 동시성 코드를 작성하면 여러 개의 스레드가 동시에 작업을 수행한다. 하지만 프로그램 안에는 Thread나 Task가 포함하지 않는 코드가 존재한다. 여러 개의 스레드가 동시에 작업을 수행하더라도 synchronized 블록이나 데이터베이스, 네트워크 API 호출 등을 만날 때 다른 스레드와 나란히 줄을 서서 순차적으로 작업을 수행 해야 하는 경우도 있다. 암달의 법칙은 프로그램이 낼 수 있는 속도의 상한이 이런 순차적 코드가 사용하는 시간에 의해서 제한된다고 말하는 것이다. 이러한 순차적 코드의 또 다른 이름은 블로킹blocking 콜이다. 문제는 스레드 자체 가 아니라 스레드를 사용하면서 자기도 모르게 만들어내는 블로킹 콜이다. 조금 과장해서 말하자면 자바 개발자가 스레드를 이용해서 만들어내는 ‘동시성’ 코드는 일종의 신기루다. 사실은 코드 곳곳에 존재하는 블로킹 콜, 순차적 코드 때문에 전 체적인 프로그램의 처리율은 이미 상한이 정해져 있지만 여러 개의 스레드가 ‘동시에’ 동작한다는 사실로부터 위안을 받을 뿐이다.
출처: https://hamait.tistory.com/612 [HAMA 블로그]
https://dzone.com/articles/how-much-memory-does-a-java-thread-take
https://3dmpengines.tistory.com/2003
https://hamait.tistory.com/612
https://qastack.kr/programming/5483047/why-is-creating-a-thread-said-to-be-expensive
https://stackoverflow.com/questions/11700763/thread-pool-vs-many-individual-threads