프로세스와 스레드
멀티태스킹과 멀티프로세싱
만약 프로그램을 두개 이상 동시에 실행한다고 가정해보자. 연산을 처리할 수 있는 cpu 코어는 1개만 있다고 가정한다.
하나의 cpu 코어가 매우 빠르게 두개의 작업을 번갈아 가면서 처리하게 되면 사람은 이것이 같이 동시에 실행된다고 느끼게 된다. 이렇게 각 프로그램의 실행 시간을 분할해서 마치 동시에 실행되는 것 처럼 하는 기법을 시분할 기법이라고 한다.
그리고 이렇게 하나의 컴퓨터 시스템이 동시에 여러 작업을 수행하는 것을 멀티태스킹 이라고 한다.
cpu에 어떤 프로그램이 얼마만큼 실행될지는 운영체제가 결정하는데 이것을 스케줄링 이라고 한다.
이때 단순히 시간으로만 작업을 분할하지는 않고, cpu를 최대한 활용할 수 있는 다양한 우선순위와 최적화기법을 사용한다. 우리는 운영체제가 스케줄링을 수행하고, cpu를 최대한 사용하면서 작업이 골고루 수행될 수 있게 최적화 한다는 정도로 이해하면 충분하다.
멀티 프로세싱
cpu 코어가 둘 이상이면 어떻게 될까
과거에는 하나의 cpu안에 보통 하나의 코어만 있었지만, 최근에는 하나의 cpu안에 2개 이상의 코어가 들어있다.
코어의 갯수 만큼 물리적으로 프로그램의 실행 대수가 달라진다 코어가 4개라면 작업 4개를 동시에 처리할 수 있게 되는것이다.
멀티 프로세싱 시스템은 하나의 cpu 코어만을 사용하는 시스템보다 동시에 더 많은 작업을 처리할 수 있게 된다.
멀티프로세싱 - 하드웨어 장비의 관점
멀티태스킹 - 운영체제 소프트웨어의 관점
프로세스와 스레드
프로그램은 실제 실행하기 전까지는 단순한 파일에 불과하다.
프로그램을 실행하면 프로세스가 만들어지고 프로그램이 실행된다.
운영체제 안에서 실행중인 프로그램을 프로세스라고 한다.
프로세스는 하나이상의 스레드를 반드시 포함하게된다.
스레드는 프로세스 내에서 실행되는 작업의 단위이다. 한 프로세스 내부에서 여러 스레드가 존재할 수 있으며, 이들은 프로세스가 제공하는 동일한 메모리 공간을 공유한다.
프로그램이 실행된다는 것은 어떤 의미일까
프로그램을 실행하면 운영체제는 먼저 디스크에 있는 파일 덩어리인 프로그램을 메모리로 불러오면서 프로세스를 만든다.
프로그램이 실행된다는 것은 사실 프로세스 안에 있는 코드가 한 줄씩 실행되는 것이다.
보통 main부터 시작해서 순서대로 내려가면서 실행된다.
결론적으로, 프로세스의 코드를 실행하는 흐름을 스레드 라고 한다. 스레드는 번역하면 실, 실을 꿰다 라는 의미이며 비유를 하면 하나씩 코드를 읽어가며 실처럼 꿴다라는 의미이다.
프로세스는 실행 환경과 자원을 제공하는 컨테이너, 스레드는 cpu를 사용해서 코드를 하나하나 실행하는 것이 스레드이다.
스레드가 하나만 있어도 될 것 같은데 왜 여러개가 필요할까?
멀티스레드가 필요한 이유
하나의 프로그램도 그 안에서 동시에 여러작업이 필요하다.
스레드를 사용하면 작업을 병렬적으로 처리가 가능하게 해준다.
스레드와 스레드 스케줄링
단일 코어 스케줄링
운영체제는 내부에 스케줄링 큐를 가지고 있고, 각각의 스레드는 스케줄링 큐에서 대기한다.
cpu 코어 하나에서 스케줄링 큐에있는 스레드 작업을 하나씩 실행시킨다.
단순히 시간 순으로만 작업을 분할하는 건 아니다, cpu를 최대한 활용할 수 있는 다양한 우선수위와 최적화 기법을 사용한다. 운영체제가 골고루 수행되게 최적화 해준다는 정도로 이해하자.
프로세스는 실행 환경을 제공한다. 여기에는 메모리 공간, 파일 핸들, 시스템 자원등이 포함된다. 이는 프로세스가 컨테이너 역할을 한다는 의미이다.
컨텍스트 스위칭
멀티태스킹이 반드시 효율적인 것은 아니다.
컴퓨터의 멀티태스킹
cpu코어가 하나만 있다고 가정한다.
멀티태스킹을 해야하기 때문에 스레드 A를 계속 실행할 수 없다. 스레드 A를 잠시 멈추고, 스레드 B를 실행한다. 이후에 스레드 A로 그냥 돌아갈 수 없다. CPU에서 스레드를 실행하는데, 스레드 A의 코드가 어디까지 수행되었는지 위치를 찾아야 한다. 그리고 계산하던 변수들의 값을 CPU에 다시 불러들어야 한다.
컨텍스트 - 현재 작업하는 문맥을 뜻함.
현재 작업하는 문맥이 변하기 때문에 컨텍스트 스위칭이라고 한다.
컨텍스트 스위칭 과정에서 이전에 실행중인 값을 메모리에 잠깐 저장하고, 이후에 다시 실행하는 시점에 저장한 값을 cpu에 다시 불러와야 한다.
결과적으로 컨텍스트 스위칭 과정에는 약간의 비용이 발생한다.
멀티스레드는 대부분 효율적이지만, 컨텍스트 스위칭 과정이 필요하므로 항상 효율적인 것은 아니다.
cpu 코어가 2개
cpu 코어가 2개 있다면 스레드1, 스레드2로 나누어 멀티스레드로 병렬 처리하는게 효율적이다. 모든 cpu를 사용하므로 연산을 2배 빠르게 처리할 수 있다.
cpu 코어가 1개인데 스레드를 2개로 만들어 연산하면 중간중간 컨텍스트 스위칭 비용이 발생한다.
운영체제 스케줄링 방식에 따라서 다르겠지만 스레드1을 1
1000 정도까지 연산한 상태에서 잠시 멈추고 스레드2를 5001
6001 까지 연산하는식으로 반복할 수 있다.
이때 cpu는 스레드1을 멈추고 다시 실행할 때 어디까지 연산했는지 알아야하고, 그 값을 cpu에 다시 불러와야 한다. 결과적으로 이렇게 반복할 때 마다 컨텍스트 스위칭 비용이든다.
스레드가 하는 작업 2가지
cpu-바운드 작업
- cpu의 연산 능력을 많이 요구하는 작업
- 데이터처리 알고리즘 실행등 cpu의 처리 속도가 작업 완료 시간을 결정하는 경우 사용
i/o 바운드 작업
- 디스크 네트워크 파일시스템 등과 같은 입출력 작업을 많이 요구하는 작업
- i/o작업이 완료될 때까지 대기시간이 많이 발생하며, cpu는 상대적으로 유휴 상태에 있는 경우가 많다. 스레드가 cpu를 점유하지 않는 상태를 의미한다.
웹 애플리케이션 서버
결론적으로만 말하면 웹 애플리케이션 서버에는 cpu 바운드 작업보다 i/o 바운드 작업이 월등히 많다.
사용자의 요청을 하나 처리하는데 cpu가 1% 사용된다면, 대부분 데이터 베이스 서버에 어떤 결과를 조회하면서 기다리다고 가정하자. 이때는 스레드는 cpu를 거의 사용하지않고 대기한다.
그렇다고해서 4코어라고 가정한 cpu에서 4개의 코어만 사용한다면 손해다 100% 사용을 원하면 100 스레드를 사용해서 cpu사용량을 최적화 시켜야한다. cpu가 놀지않게 실무에 성능 테스트를 통해서 최적의 숫자를 찾아나가는 것이 이상적이다.
'BackEnd > Java' 카테고리의 다른 글
[Java] synchronized - 동기화 (0) | 2024.08.19 |
---|---|
[Java] 메모리 가시성 - volatile (0) | 2024.08.19 |
[Java] 컬렉션 프레임워크 와 배열, 리스트 (3) | 2024.07.24 |
[Java] 예외 계층과 실무에서의 예외 처리 방법 (0) | 2024.07.17 |
[Java] Exception과 throw, throws, try catch 가 언제 사용 되는가 (0) | 2024.07.16 |