개발 서적 리뷰/게임서버 프로그래머 책
[게임서버프로그래밍#8] 병렬성, 싱글/멀티스레드 서버, 세마포어, 병렬 자료구조
거북이의 기술블로그
2024. 5. 26. 16:16
이 글에서는 병렬 처리의 기본 개념부터, 싱글스레드 서버와 멀티스레드 서버의 차이, 세마포어의 역할,
그리고 병렬 자료구조까지 실제 서버 개발에서 반드시 고려해야 할 병렬성 이슈를 다룬다.
병렬성(Parallelism)이란
정의:
병렬성은 여러 작업을 동시에 수행하는 능력을 의미한다.
CPU의 여러 코어를 활용하거나, I/O 대기 시간 동안 다른 작업을 처리하여 시스템 자원을 최대로 활용하는 것이 목적이다.
진짜 병렬성:
- 하드웨어적으로 여러 코어가 동시에 다른 작업을 수행하는 것
논리적 병렬성:
- 하나의 코어에서 여러 작업이 번갈아가며 실행되는 것(비동기 처리 포함)
싱글스레드 서버
- 하나의 스레드만 사용하여 모든 작업을 처리하는 서버이다.
- 장점: 구조가 단순하고 디버깅이 쉽다.
- 단점: 다수 클라이언트 접속 시 병목 현상이 발생한다.
* CPU 사용 방법
- CPU 하나당 프로세스를 하나씩 띄워 병렬 효과를 얻을 수 있다.
- 하지만 메모리를 공유하지 않기 때문에 **프로세스 간 통신(IPC)**이 필요하다.
문제점:
- 컨텍스트 스위칭(프로세스 간 전환) 비용이 크다.
멀티스레드 서버
- 하나의 프로세스 내에 여러 스레드를 생성하여 각 스레드가 클라이언트를 담당한다.
- 장점: 동시에 많은 클라이언트를 처리할 수 있다.
- 단점: 스레드 간 자원 공유로 인한 충돌(race condition) 관리가 필요하다.
* CPU 사용 방법
- 보통 코어 수만큼 스레드를 생성하여 CPU를 최대로 활용한다.
- 만약 디바이스 접근(IO 작업)이 많은 경우, 코어 수보다 더 많은 스레드를 운영할 수도 있다.
예시:
- 4코어 CPU에서, 평균적으로 CPU 사용 25%(1/4) + IO 대기 75%(3/4)라면 스레드를 4×3=12개 정도 돌리는 전략을 쓸 수 있다.
- (I/O작업으로 3/4을 사용하고 있기에, 4*3으로 계산)
세마포어(Semaphore)란
정의:
세마포어는 공유 자원에 접근할 수 있는 스레드 수를 제한하는 동기화 도구이다.
사용 예시
- 서버에서 동시에 최대 10명까지만 파일 다운로드를 허용하고 싶을 때, 세마포어를 이용하여 10개 슬롯을 관리한다.
- 10개 슬롯이 모두 찼으면 새로운 요청은 대기하게 된다.
멀티스레드 개발 시 흔히 하는 실수
1. 락 없이 공유 데이터 접근
- 읽기/쓰기를 동시에 하면 데이터가 망가질 수 있다.
2. 락 순서 꼬임(Deadlock)
- A 락 → B 락 순으로 잡아야 하는데, 다른 스레드가 B 락 → A 락을 잡으면 교착상태에 빠진다.
3. 과도한 락 범위
- 락을 너무 넓게 걸면 스레드 병렬성이 떨어져 전체 성능이 급감한다.
4. 디바이스 타임(Device Time) 내에서 락 잡기
- 디스크 IO나 DB 호출 같은 느린 작업을 락 걸고 하면 CPU가 놀게 되어 전체 시스템 성능이 하락한다.
5. 잠금 전염성 문제
- 락이 해제되었는데, 락으로 보호하던 객체(포인터 등)를 다른 스레드가 참조하는 경우 발생할 수 있다.
병렬 자료구조란
- 락을 사용하지 않고도 멀티스레드 환경에서 안전하게 사용할 수 있는 자료구조를 말한다.
- 대표적으로 락 프리(무락) 큐(Queue), 스택(Stack) 등이 있다.
특징:
- 내부적으로 원자적(atomic) 연산을 사용하여 데이터 일관성을 보장한다.
- 성능이 매우 빠르지만 설계가 복잡하다.
* 병렬 처리 시 주의사항
항목 | 주의사항 |
락 관리 | 과도한 락, 락 순서 꼬임 피해야 한다 |
디바이스 타임 고려 | 느린 작업은 락 안에서 하지 않는다 |
병렬 자료구조 활용 | 가능하면 락 없는 자료구조를 사용해 병목 줄인다 |