자바 스레드는 OS 스레드와 1:1로 매핑되며 OS 스케쥴러에 의해 스케쥴링 된다. 즉 자바 스레드 1개가 생성되면 os의 스레드도 한개 생성된다.
new Thread()를 하면 스레드 객체가 생성되고 start()를 다음과 같은 동작이 실행된다.
CPU 코어는 한정되어 있고 스레드는 많기 때문에, OS의 스케줄러(Scheduler)가 누구를 실행시킬지 결정한다.
스레드가 구동되는 핵심은 "줬다 뺏기"이다. 한 스레드가 코어를 독점하지 못하도록 OS는 아주 짧은 시간(Time Quantum)만 허락한다.
TCB(장부) 작성 → 스택 할당 → CPU 레지스터에 값 로딩 → 실행 → 시간 다 되면 레지스터 값 저장 후 교체"의 무한 반복이다.
병렬성은 직관적으로 명령어를 메모리에서 뽑아 해석하고 실행하는 반도체 유닛인 여러개의 코어에 맞춰 여러개의 프로세스, 스레드를 돌려 병렬로 작업들을 동시 수행하는 것을 말한다.
듀얼코어, 쿼드코어, 옥타코어 등등 이런 명칭이 붙는 멀티코어 프로세서가 달린 컴퓨터에서 할 수 있는 방식이다.
동시성은 둘 이상의 작업이 동시에 실행되는 것을 의미한다. 이 '동시' 라는 의미에서 병렬성과 동시성의 한글 의미가 헷갈릴수 있다. Parallelism가 물리적으로 정말로 동시에 실행하는 것이라고 하면, Concurrency는 동시에 실행하는 것처럼 보이게 하는 것으로 이해하면 된다.
여러 작업을 동시에 처리하는 것처럼 보이게 만들어, 사용자에게 더 빠른 반응성을 제공하기 위해서다. 그리고 이렇게 진행 중인 작업들을 A → B → C → D 로 번갈아 바꾸는 것을 Context Switching 이라고 부른다.
코어 개수보다 실행해야하는 스레드가 많을때 사용합니다.
타이머 인터럽트가 없다면 독점 문제가 생길 수 있다. 한 스레드가 무한 루프에 빠지거나 아주 긴 계산을 시작하면, 그 스레드가 끝날 때까지 CPU 코어를 절대 놓아주지 않을 것이다. 그렇게 되면 마우스 클릭도 안 먹히고, 다른 프로그램들이 모두 멈춰버리는 '프리징(Freezing)' 현상이 발생한다.
그래서 OS는 타이머 인터럽트라는 장치를 사용한다. 하드웨어 타이머가 일정 시간(Time Slice)마다 CPU에 "자, 시간 다 됐어! 다음 사람한테 넘겨!"라는 전기 신호를 강제로 보낸다.
이 신호를 받은 CPU는 하던 일을 멈추고 제어권을 OS에게 넘긴다. 이 때문에 모든 스레드가 조금씩이라도 CPU를 나누어 쓸 수 있게 되는 것이다.
스레드 구동 방식은 동시성과 병렬성 둘 중 한 방식으로 일어날 수 있다. 보통은 병렬성과 동시성이 혼합되어 일어난다.
요즘 스마트폰이나 PC는 보통 4코어, 8코어 이상이다. 즉 병렬성과 동시성이 함께 일어난다.
그런데 우리는 보통 스레드를 8개만 쓰지 않는다. 크롬 브라우저, 카카오톡, 자바 프로그램, 백신 등 수백 개의 스레드가 떠 있다.
코어는 8개인데 스레드가 500개라면?
8개의 코어가 각각 수십 개의 스레드를 맡아서 번갈아 가며(동시성) 처리한다. 결과적으로 전체 시스템 관점에서는 병렬(8개 코어가 동시에 일함)이면서, 각 코어 내부에서는 동시성(번갈아 가며 일함)이 일어나는 구조이다.