- 클라이언트에게 수 많은 요청을 받는 웹 서버가 존재할 때, 스레드라는 개념이 없으면 발생하는 문제
- 요청이 들어올 때 마다 새로운 프로세스를 생성해서 작업해야 함, 이는 자원, 시간 소요가 매우 크고 프로세스 간 컨텍스트 스위칭은 오버헤드가 큰 작업
- IPC를 활용해야 하는데 이 또한 오버헤드가 큼
- 멀티프로세싱의 무거움을 해소하기 위해 탄생한 개념 = 스레드
스레드 사용 이유
- 프로세스에 비해 메모리를 적게 사용
- 스레드 컨텍스트 스위칭이 프로세스 컨텍스트 스위칭보다 빠름
- 스레드 간에는 메모리를 공유하므로 통신을 위해 IPC를 사용하지 않아도 됨
스레드란
- 하나의 프로세스에서 실행 흐름의 단위
- 하나의 프로세스 내에서 스레드 간에 공유하는 것
- 코드 영역, 데이터 영역, 힙 영역
- 하나의 프로세스 내에서 스레드 간에 공유하지 않는 것
- 프로그램 카운터, 레지스터 정보, 스택 영역
- 코드 실행과 직결된 부분
싱글 스레드
- 하나의 프로세스에서 하나의 스레드만 실행
장점
- 공유 자원을 접근하는 동기화 문제를 신경쓰지 않아도 됨
- 컨텍스트 스위칭을 요구하지 않아서 전환 비용이 들지 않음
단점
- 여러 CPU를 활용하지 못함
멀티 스레드
- 하나의 프로세스에서 다수의 스레드 실행
- 프로세스 내에서 자원을 공유하여 자원 생성과 관리 중복을 최소화
- 서버가 많은 요청을 효율적으로 수행할 수 있는 환경 제공
- 각각의 스레드가 고유의 레지스터와 스택으로 표현
장점
- Responsiveness(응답성)
- 동시에 여러 작업을 수행할 수 있으므로 응답 속도 향상
- Resource Sharing(자원 공유)
- 스레드 간 자원 공유를 통해 통신의 효율 증가
- Economy(경제성)
- 프로세스 생성에 비해 메모리와 자원 할당의 비용이 적음
- Scalability(확장성)
- 단일 스레드 프로세스는 CPU가 아무리 많아도 하나의 CPU만 사용 가능
단점
- 메모리 공간을 공유하기 때문에 동기화, 교착 상태와 같은 문제가 발생 가능
스레드 컨텍스트 스위치
- 프로세스 컨텍스트 스위치와 동작 방식은 동일
- PCB(Process Control Block)과 마찬가지로 TCB(Thread Control Block)라는 자료 구조 존재
- 스레드 컨텍스트 스위치가 빠른 이유
- 다른 프로세스는 다른 메모리 주소를 가지기 때문에, 컨텍스트 스위칭을 하는 과정에서 다른 메모리 주소를 참조해야 하고, 캐시 버퍼를 필수적으로 사용
- 스레드는 메모리 주소를 공유하기 때문에 계속 같은 메모리 주소만 참조하면 되므로 캐시, 버퍼를 사용하는 과정을 생략
멀티 스레딩
멀티 스레딩 사용 예
Java의 스레드 만들기 3가지
- Thread 클래스 상속
public class Threadtest extends Thread {
public void run() {
try {
System.out.println("1번 방법 Thread test");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
- Runnable 인터페이스 구현
public class Threadtest2 implements Runnable {
@Override
public void run() {
try {
System.out.println("2번 방법 Thread test");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
public class Threadtestmain {
public static void main(String[] args) {
Threadtest2 test=new Threadtest2();
Thread test2 = new Thread(test);
test2.start();
}
}
- 람다 표현식 사용
public class Threadtestmain {
public static void main(String[] args) {
Thread test2 = new Thread(() -> {
try {
System.out.println("3번 방법 Thread test");
} catch (Exception e) {
System.out.println(e.getMessage());
}
});
test2.start();
}
}
자바에서의 스레드 관리
- join
- 자식 스레드가 join 메소드를 실행하면 부모는 자식이 끝날 때 까지 대기해야 함
- interrupt
- 스레드 종료
스레드의 종류
User Thread
- 유저 모드에서 사용하는 스레드. 즉, 개발자가 만드는 스레드
- 운영체제는 이 유저 모드의 스레드를 지원하지 않음, 정확히는 인식을 못함
- 운영체제는 커널 모드에서 프로세스만 볼 수 있고, 프로세스가 유저 모드에서 각 스레드들을 보고 있는 구조, 따라서 운영체제가 PCB를 관리하고, 프로세스가 TCB를 관리
- Green Thread 라고도 불림
장점
- 스레드 컨텍스트 스위칭을 프로세스 내부에서 진행하기 때문에 오버헤드가 적음
- 유저 모드와 커널 모드의 전환이 없으므로 오버헤드가 적음
단점
- 프로세스 내에서 하나의 스레드가 중단되면 다른 스레드도 같이 중단
- 커널이 유저 스레드를 인식하지 못하여 하나의 스레드가 중단되면 그냥 프로세스 자체를 대기상태로 바꿔두기 때문
Kernel Thread
- 커널 모드에서 사용하는 스레드
- 커널이 스레드의 생성 및 스케쥴링을 관리
- native thread라고도 불림
장점
- 커널이 알아서 스레드를 관리
- 프로세스 내에서 하나의 스레드가 중단되어도 커널이 다른 스레드들을 계속 실행
- 멀티 프로세싱 환경에서 스레드들을 각각 다른 프로세스에 할당 가능
단점
- 스케쥴링과 동기화를 위해 시스템 콜을 호출하는 과정에서 오버헤드 발생
- 유저 모드와 커널 모드의 전환이 빈번하므로 오버헤드가 많음
유저 스레드, 커널 스레드의 관계
- Many to One Model
- 커널 스레드 1개에 유저 스레드 N개가 연결된 모델
- 커널 스레드는 유저 스레드가 몇개 있는지 모르기 때문에 유저 스레드에서 I/O 작업이 하나라도 발생하면 해당 프로세스는 I/O가 풀릴 때 까지 block 상태가 됨
- One to One
- 커널 스레드 1개에 유저 스레드 1개가 연결된 모델
- 효율이 좋지 않음
- Many to Many
- 커널 스레드 N개에 사용자 스레드 N개가 혼합되어 연결된 모델
Thread Pool
사용 이유
- 프로세스 실행 중 병렬 작업 처리가 많아지면 스레드 개수가 증가, 그로 인한 스레드 생성 및 스케쥴링 작업 등의 이유로 CPU에 많은 부하가 갈 수 있음
- 스레드를 매 작업마다 새로 생성하는 것이 아닌 미리 설정해 둔 개수로 만들어 두고, 작업이 요청될 때 마다 각 스레드에서 할당해서 처리하는 방식이 효율적
- 이러한 과정을 Thread Pool 이라고 함
'CS > 운영체제' 카테고리의 다른 글
메인 메모리 (0) | 2023.06.19 |
---|---|
데드락(Deadlock) (0) | 2023.03.26 |
스핀락, 뮤텍스, 세마포어 (0) | 2023.03.19 |
프로세스의 이해 & 프로세스간 통신 (0) | 2023.02.26 |
1강 운영체제 개요 (0) | 2023.02.21 |