멀티 스레드
일반적으로 하나의 프로세스는 하나의 스레드를 가지고 작업을 수행하게 된다. 멀티 스레드
란 하나의 프로세스 내에서 둘 이상의 스레드가 동시에
작업을 수행하는 것을 의미한다.
멀티 스레딩의 장점
멀티 스레드
는 각 스레드가 자신이 속한 프로세스의 메모리를 공유하므로, 시스템 자원의 낭비가 적다. 특히 스레드의 문맥 교환
은 프로세스의 문맥 교환과 달리 캐시 메모리를 비울 필요가 없기 때문에 더 빠르다. 따라서 시스템의 처리율
이 향상되고 자원 소모
가 줄어들어 자연스럽게 프로그램의 응답 시간
이 단축된다. 또한, 하나의 스레드가 작업을 할 때 다른 스레드가 별도의 작업을 할 수 있어 사용자와의 응답성
도 좋아진다. 이러한 장점 때문에 여러 프로세스로 할 수 있는 작업들을 하나의 프로세스에서 스레드로 나눠 수행하는 것이다.
멀티 스레딩의 단점
멀티 스레딩
을 기반으로 프로그래밍을 할 때는 주의해야 할 점이 있다. 여러 개의 스레드가 데이터와 힙 영역을 공유하기 때문에 동시에 접근을 시도 할 때 접근의 타이밍이나 순서 등이 결괏값에 영향을 줄 수 있다는 것이다. 그렇기 때문에 멀티 스레딩 환경에서는 동기화
작업이 필요하다.
동기화란?
시스템의 한정적인 자원에 여러 스레드가 동시에 접근해서 사용하려고 하면 문제가 발생할 수 있다. 이런 문제를 방지하기 위해 스레드들에게 하나의 자원에 대한 처리 권한
을 주거나 순서를 조정
해주는 기법이다.
하지만 이로 인해 병목현상
이 발생하여 성능이 저하될 가능성이 높다.
병목현상(Bottleneck)
병목현상
은 전체 시스템
의 성능이나 용량이 하나의 구성요소
로 인해 제한을 받는 현상을 말한다. 병의 몸통(전체 시스템)
보다 입구(하나의 구성요소)
부분이 좁아서 물이 상대적으로 천천히 쏟아지는 것과 비슷한 현상이다.
공유 자원이 아닌 부분까지 과도하게 동기화를 하게 되면 현재 스레드는 락(lock)
을 획득한 스레드가 종료하기 전까지 대기해야 한다. 그렇게 되면 전체 성능에 악영향을 미치게 된다. 따라서 동기화를 하고자 할 때는 메소드 전체를 동기화 할 것인지, 아니면 특정 부분만 동기화할 것인지를 고민해야 한다.
임계 영역(Critical Section)
두 개 이상의 프로세스가 동시에 사용할 수 없는 자원에 대해 접근하고 실행하는 프로그램 내의 코드
부분을 임계 영역
이라고 한다.
멀티 스레딩
에서는 스레드가 자원을 공유하고 있기 때문에 동일한 자료에 동시에 접근할 때 결과가 달라지는 임계 영역이 발생할 수 있다. 임계 영역
의 성공적인 실행을 위해서는 가장 먼저 상호 배제
가 지켜져야 하고, 상호 배제
란 한 번에 하나의 프로세스만이 임계 영역에 들어가야 함을 의미한다.
임계 영역을 해결하기 위한 방법은 크게 세 가지가 있다.
- 뮤텍스(Mutual Exclusion, Mutex)
뮤텍스
는 공유 자원을 사용하기 전에 설정하고 사용한 후에 해지하는잠금
이다. 사물함의 특정 칸을 자물쇠로 잠궈놓고 사용하면 본인 외에는 아무도 사용할 수 없는 것처럼, 뮤텍스로 잠금이 설정되면 다른 스레드는 잠긴 코드 영역에 접근할 수 없다. 뮤텍스는잠금
or잠금 해제
둘 중 하나의 상태만을 가지게 된다.
- 세마포어(Semaphore)
세마포어
는 다익스트라가 처음 제안한 개념으로, 특수한 명령들만 접근할 수 있게 허용되는 보호된변수
이다. 현재 공유자원에 접근할 수 있는 스레드, 프로세스의 수를 나타내며, 뮤텍스와 비슷한 역할을 하지만 세마포어는 동시 접근 동기화보다는접근 순서 동기화
와 더 관련이 있다.
예를 들어, 프린터가 10개 있는 실습실에서 비어있는 프린터가 있다면 누구나 출력 작업을 할 수 있도록 해보자. 그럼 아래와 같이 생각할 수 있다.
프린터
: 공유자원출력 작업
: 임계 영역세마포어
: 작업 가능한 프린터 대수(초기값: 10)
프린터가 빌 때마다 새로운 사람이 출력 작업을 시작할 수 있고, 이처럼 한 번에 많은 인원을 수용할 수 있다는 점이 뮤텍스와의 차이점이다.
세마포어에 접근 가능한 명령들은 크게 P 명령
과 V 명령
이 있다. P 명령은 wait
또는 down
이라고 불리기도 하며, V 명령은 signal
또는 up
이라는 이름으로 사용되기도 한다.
🤷♀️ 왜 다익스트라는 P와 V로 이름을 붙였을까?
다익스트라가 태어난 곳인 네덜란드에서는 깃발을 내리다(down)
의 동사가 P
로 시작하고, 올리다(up)
의 동사는 V
로 시작한다. 도로 공사 중인 현장에서 깃발을 사용해 차량 통행을 제어하는 경우를 세마포어에 적용한 것이다.
P 명령(wait, down)
: 자신의 차례가 올 때까지 대기 ("멈춰~")V 명령(signal, up)
: 다음 프로세스로 순서를 넘겨줌 ("지나가~")
P(S): if(S > 0)
then S = S - 1;
else
S > 0 조건 만족될 때까지 큐에서 대기;
V(S): if(큐에서 대기 중인 프로세스들이 존재)
then 그 중 한 프로세스를 준비 or 실행 상태로 만듦;
else
S = S + 1;
- 모니터(Monitor)
모니터
는 둘 이상의 스레드나 프로세스가 공유 자원에안전하게
접근할 수 있도록 공유 자원을 숨기고 해당 접근에 대한인터페이스
만 제공하는모듈
이다. 시스템이 모니터라는 큰 틀을 제공해주면, 우리는 이 구조를 활용하여 이 안에 추가적인 코딩을 하여 임계 영역을 관리하는 것이다. 꽤 많은 부분을 시스템이 대신 해주기 때문에 사용자의 실수 위험을 줄일 수 있다.
모니터는모니터 큐
를 통해 공유 자원에 대한 작업들을순차적
으로 처리한다. 또한 언제나 모니터의 진입을 하나의 프로세스로 제한한다. 즉, 한 번에 하나 이하의 프로세스만이 모니터 내에 있게 함으로써상호 배제
를 자연스럽게 실현할 수 있다.세마포어
에서는 상호 배제를명시적
으로 구현해야 한다는 것이 모니터와의 차이점이다.
뮤텍스 vs 모니터
구분 |
뮤텍스 |
모니터 |
---|---|---|
사용 목적 |
동기화 대상 하나 | 동기화 대상 여러개 |
제공자 |
운영체제 커널 | 프레임워크 or 라이브러리 ( Java 는 기본적으로 모든 객체에 모니터 제공) |
락(lock) |
O | X |
속도 |
느림 | 빠름 |
세마포어 vs 모니터
구분 |
세마포어 |
모니터 |
---|---|---|
상호 배제 구현 |
사용자가 명시 | 자동 구현 |
뮤텍스 vs 세마포어
구분 |
뮤텍스 |
세마포어 |
---|---|---|
동기화 목적 |
동시 접근 동기화 | 접근 순서 동기화 |
동기화 개수 |
1개 | 1개 이상 |
소유 |
가능(key) | 불가능 |
접근 가능한 공유 자원의 개수가 1개 이하라면 이진 세마포어
로 뮤텍스
처럼 활용할 수 있다. 그래서 세마포어는 뮤텍스가 될 수 있지만, 뮤텍스는 세마포어가 될 수 없는 것이다.
셀프 계산대
가 한 개 밖에 없는 무인마트에서는 현재 계산 중인 사람이 계산을 마쳐야 다음 사람이 계산을 할 수 있다. 이렇게 한 번에 하나의 작업만 처리하는 것이 뮤텍스
이다. 하지만 셀프 계산대가 여러 대라면 동시에 여러 사람이 계산을 진행할 수 있고, 계산을 기다리던 사람은 비어있는 아무 계산대에 가서 계산을 하면 된다. 이처럼 동시에 여러 개의 작업을 처리하는 것이 세마포어
이다.
계산대가 여러개인 마트에 뮤텍스
를 적용한다는 것은 각 사람마다 맘에 드는 계산대를 하나씩 정해서 그 앞에서만 대기하는 것이다. 내 옆의 계산대가 비더라도 나는 현재 계산대를 선택했기 때문에 비어있는 곳으로 갈 수 없는 것이다. 굉장히 비효율적이다.
따라서 어떤 경우에 뮤텍스를 적용하고 세마포어를 적용할 것인지 적절하게 결정해야 한다.
한 눈에 비교하는 멀티 스레드 vs 멀티 프로세스
구분 |
멀티 스레드 |
멀티 프로세스 |
---|---|---|
개념 |
하나의 프로세스에 여러 스레드로 자원을 공유하며 작업을 나누어 수행 |
두 개 이상의 프로세서(CPU)가 하나 이상의 작업을 동시에 처리(병렬처리) |
동시성 |
O | O |
메모리 공간 |
적게 차지 | 많이 차지 |
문맥 전환 |
빠름 | 느림 |
독립성 |
특정 스레드 종료 시 전체 스레드 종료될 수 있음 |
각 프로세스는 독립적이기에 영향 없음 |