👩🏻‍💻기초지식/CS

[OS] 프로세스와 멀티 프로세스, 스레드와 멀티 스레스

공대 컴린이 2023. 10. 23. 14:39
728x90

프로세스

프로세스란 실행파일이 메모리에 적재되어 CPU를 할당받아 실행되는 것을 말합니다.

 

멀티 프로세스

멀티 프로세스는 프로세스가 2개 이상 동시에 실행되는 것을 말합니다. 이때, 동시에 라는 말은 동시성과 병렬성 두 가지를 의미합니다.

동시성(병행성)은, CPU 코어가 1개일 때 즉, 단일 프로세서일 때, 여러 프로세스를 짧은 시간동안 번갈아가며 연산하는 시분할 시스템으로 실행되는 것이다.

병렬성은 CPU 코어가 여러 개일 때 즉, 멀티 프로세서일 때, 각각의 코어가 각각의 프로세스를 연산함으로써 실제 프로세스가 동시에 실행되는 것을 말합니다.

 

> 프로세스와 프로세서

프로세스(process)는 프로그램의 실행 상태를 말하고, 프로세서(processer)는 CPU 코어를 일컫는 말이다.
즉, 멀티 프로세스는 하나의 프로그램에서 여러 개의 프로세스를 실행하는 것을 의미하고, 멀티 프로세서는 여러 개의 CPU 코어가 하나의 시스템에서 동시에 실행되는 것을 의미한다.

 

멀티 프로세스의 장단점

장점은, 독립된 구조이기 때문에 안정성이 높고, 여러 프로세스가 동시에 일하므로 하나의 프로세스가 죽어도 문제가 확산되지 않는다는 것입니다. 또한 여러 개의 프로세스가 처리되어야 할 때 동일한 데이터를 사용하고, 이러한 데이터를 하나의 디스크에 두고 모든 프로세서(CPU)가 이를 공유하면 비용적으로 저렴해집니다.

 

단점은, 멀티 스레드보다 많은 메모리 공간과 CPU 시간을 차지하고, 독립된 메모리 영역이므로 작업량이 많을수록 Context Switching이 자주 일어나 오버헤드 발생으로 인한 성능저하가 있습니다.

 

Context Switching 과정에서 캐시 메모리 초기화 등의 무거운 작업이 진행되므로 많은 시간이 소모될 수 있습니다. 이는, 프로세스가 각각의 독립된 메모리 영역을 할당받았기 때문에 프로세스 사이에 공유하는 메모리가 없어, Context Switching이 발생하면 캐시에 있는 모든 데이터를 리셋하고, 다시 캐시 정보를 불러와야 하는 과정때문입니다.

 

Context Switching

CPU는 한번에 하나의 프로세스만 실행할 수 있습니다. 따라서 여러 프로세스가 존재하는 경우, CPU에서 돌아가며 프로세스 작업을 처리합니다. 이러한 과정을 Context Switching이라고 합니다.

 

동작중인 프로세스가 "대기"하면서 해당 프로세스의 상태(Context)를 "보관"하고, 대기하고 있던 다음 순서의 프로세스가 "동작"하면서 이전에 보관했던 프로세스의 상태를 "복구"하는 작업을 수행합니다.

 

스레드

스레드란, 프로세스 내에서 실행되는 흐름의 단위를 말합니다. 일반적으로 하나의 프로세스는 하나 이상의 스레드를 가지고 있습니다.

 

멀티 스레드

https://wooody92.github.io/os/%EB%A9%80%ED%8B%B0-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%99%80-%EB%A9%80%ED%8B%B0-%EC%8A%A4%EB%A0%88%EB%93%9C/#%EA%B0%9C%EB%85%90

멀티 스레드는 하나의 프로세스에 여러 스레드로 자원을 공유하며 작업을 나누어 수행하는 것을 말합니다. 프로세스의 메모리 영역 중, 힙 영역과 코드 영역, 데이터 영역은 공유하여 사용하고, 스택영역은 개별적으로 사용합니다.

 

멀티 스레드의 장단점

장점은, 스레드 간 자원을 공유하여 사용하기 때문에 전체적인 시스템 자원의 소모가 줄어들어, 자원의 효율성이 좋아집니다. 또한, 스택 영역을 제외한 메모리 영역을 공유하기에 통신 비용이 적고, 힙 영역을 공유하므로 데이터를 주고받을 수 있습니다. 이로인해 스레드 간 데이터를 주고받는 것이 간단해지고, 스레드 사이의 작업량이 적어 Context Switching이 빨라집니다. (캐시 메모리를 비울 필요가 없기 때문)

 

단점은, 자원을 공유하기 때문에 스레드 간의 레이스 컨디션 같은 동기화 문제가 발생할 수 있습니다. 또한, 불필요한 부분까지 동기화하여 대기시간으로 인해 성능저하가 발생하지 않도록 주의 깊은 설계가 필요하고 디버깅이 어렵습니다.

추가적으로, 하나의 스레드에 문제가 생기면 전체 프로세스가 영향을 받습니다. 또한 단일 프로세스 시스템의 경우엔 멀티스레드를 통한 성능 향상의 효과를 기대하기 어렵습니다.

 

레이스 컨디션 (race condition, 경쟁상태)

레이스 컨디션이란, 둘 이상의 스레드가 공유 데이터에 접근하고, 그 중 적어도 하나는 데이터를 수정하려고할 때 발생할 수 있는 문제를 말합니다.

예를 들어, 1만큼을 1000번 늘리는 함수와, 1만큼을 1000번 감소하는 함수를 스레드로 각각 실행시키면, 실행 결과가 0이 아닌 다른 값이 나옵니다. 이는 두 스레드가 동시에 연산을 수행하며, 연산의 결과를 메인 메모리에 반영하기 전에 다른 스레드에서 Context Switching이 일어나며 다른 연산을 수행하게 됩니다.

 

이렇게 공유자원에 접근하는 코드 영역을 임계영역(Critical Section)이라고 합니다.

레이스 컨디션 문제를 해결하기 위해선, 임계 영역을 통해 값에 접근하는 '뮤텍스''세마포어'방식을 사용해야 합니다.


뮤텍스(Mutex, Mutual Exclusion = 상호배제)

뮤텍스는 임계영역을 가진 스레드들의 실행 시간이 서로 겹치지 않고, 한 번에 하나의 스레드만 공유 자원에 접근할 수 있도록 하는 도구입니다. 뮤텍스는 임계 영역에 대한 접근을 제어하며, 한 스레드가 임계 영역에 들어가면 뮤텍스를 '잠그고(lock)', 다른 스레드들은 뮤텍스가 '풀릴(unlock)' 때까지 대기합니다. 따라서 뮤텍스는 주로 1:1 (binary) 관계에서 사용됩니다.

 

세마포어 (Semaphore)

세마포어는 여러 개의 동일한 리소스를 다루거나, 여러 개의 스레드가 특정 코드 섹션에 진입하는 것을 제한하는 경우 등에서 사용됩니다. 세마포어는 내부 카운터를 유지하며, 이 카운터 값은 동시에 리소스를 접근할 수 있는 최대 스레드 수를 나타냅니다. 어떤 스레드가 세마포어를 요청(wait)하면 내부 카운터가 감소되고, 반대로 세마포어를 반환(signal)하면 카운터 값이 증가합니다.

만약, 모든 리소스(카운터 값 = 0)가 사용중일 때, 추가적인 요청이 들어오면 그 요청은 대기 상태로 전환됩니다.

 

바이너리 세마포어 (Binary Semaphore)

바이너리 세마포어는 이름에서 알 수 있듯이, 세마포어의 카운트가 0 또는 1을 가질 수 있습니다. 이런 바이너리 세마포어는 뮤텍스와 매우 유사하게 작동합니다. 둘 사이의 차이점은 "소유권" 개념에 있습니다. (아래 설명)

즉, 세마포어는 뮤텍스처럼 사용될 수 있지만, 뮤텍스는 절대 세마포어처럼 사용될 수 없습니다.

 

카운팅 세마포어 (Counting Semaphore)

카운팅 세마포어는 세마포어의 카운트가 양의 정수 값을 가지며, 설정한 값 만큼 스레드를 허용하고, 그 이상의 스레드가 자원에 접근하면 락이 실행되는 것입니다.

 

뮤텍스와 세마포어의 차이점

뮤텍스는 소유 개념을 가집니다. 즉, 잠긴 뮤텍스는 반드시 그것을 잠갔던 스레드에서만 풀릴 수 있습니다.

반면, 세마포어는 (특히 바이너리 세마포어, 카운팅 세마포어) 소유 개념이 없습니다. 즉, 하나의 스레드에서 세마포어를 요청하고 다른 스레드에서 그것을 반환할 수 있습니다.


그러나, 이런 뮤텍스와 세마포어 동기화도 잘못 사용되면 병목 현상, 교착 상태, 기아 상태같은 새로운 문제를 초래할 수 있습니다.

 

교착상태 (deadlock, 데드락)

교착상태란, 둘 이상의 스레드가 서로의 작업이 끝나기만을 기다리며 작업을 더 이상 진행하지 못하는 상태를 의미합니다. 예를 들어 스레드 A가 리소스1을 소유하고, 리소스2를 요청하는 동시에 스레드 B가 리소스2를 소유하고, 리소스1을 요청한다면 두 스레드는 모두 진행되지 못하는 상황이 됩니다.

 

교착상태 발생 조건

교착상태는 네가지의 조건이 모두 충족해야 발생하게 됩니다. 이 중, 단 하나라도 충족하지 않으면 교착상태는 발생하지 않습니다.

 

1. 상호배제 : 한 스레드가 접근하는 공유자원은 다른 스레드가 접근하지 못하도록 막아야 합니다.

2. 비선점 : 한 스레드가 사용중인 동기화 자원은 중간에 다른 스레드가 빼앗을 수 없습니다.

3. 점유와 대기 : 스레드가 어떤 동기화 자원을 할당받은 상태에서 다른 동기화 자원을 기다리는 상태여야 합니다. 즉, 다른 스레드가 필요로 하는 자원을 점유하고 있으면서도, 또 다른 자원을 대기하는 상태가 되어야 합니다.

4. 순환 대기 : 점유와 대기를 하는 스레드간의 관계가 원을 이루어야 합니다. 점유와 대기하는 스레드들이 서로 방해하는 방향이 원을 이루면서 서로 양보하지 않기에 교착상태에 빠지게 됩니다.

 

교착상태 해결 방법

교착상태를 해결하기 위한 방법은 예방, 회피, 검출이 있습니다.

 

1. 예방 : 교착상태를 유발하는 네가지 조건을 무력화시킵니다.

2. 회피 : 교착상태가 발생하지 않는 수준으로 자원을 할당합니다.

3. 검출 : 자원 할당 그래프를 사용하여 교착 상태를 발견해냅니다.

 

기아 상태 (Starvation)

특정 프로세서나 스레드가 필요한 리소스를 얻지 못하여, 영구적으로 실행되지 못하는 경우를 말합니다. 

728x90