Skip to content

Latest commit

 

History

History
47 lines (24 loc) · 4.13 KB

concurrency.md

File metadata and controls

47 lines (24 loc) · 4.13 KB

동시성

동시성 프로그래밍은 다른말로 멀티스레드 프로그래밍이라고 합니다.

보통 서버는 멀티스레드로 돌아가지만 서버 자체는 단일 스레드로 코드를 짭니다.

왜냐하면 멀티스레드 프로그래밍은 제대로 짜기가 어렵기 때문입니다.

멀티스레드 프로그래밍을 하는 순간 디버깅부터 시작해서 재현이 불가능한 버그 등이 간헐적으로 나타나고 테스트를 작성하는 것 또한 까다로워집니다.

멀티스레드 프로그래밍이 어려운 이유

스레드를 만들고 없애는 것도 큰 일이지만, 여러 스레드에서 공유하는 자원에 대한 접근을 조율하는 과정에서 복잡한 일이 맣이 일어납니다.

공유 자원에 대한 접근을 제대로 제어하지 못한다면, 단일 스레드 애플리케이션에서는 볼 수 없었던 여러 유형의 버그들을 볼 수 있습니다.

스레드

스레드는 애플리케이션 실행에 있어서 하나의 기본 단위입니다. 실행중인 애플리케이션은 최소 하나의 스레드로 구성됩니다.

각 스레드는 별도의 스택을 가지며, 독립적으로 동작합니다.

같은 프로세스의 스레드끼리는 파일 핸들이나 메모리 같은 자원을 공유합니다. 이 공유 자원에 대한 접근을 제대로 제어하지 못한다면 문제가 생길 수 있습니다.

예를 들어, 동시에 쓰기 작업을 수행한다면 데이터 손상 같은 부작용이 흔히 생기곤 합니다.

스레드는 여러 방식으로 구현할 수 있습니다. 운영체제에서 지원하는 스레드는 네이티브 스레드 또는 커널 수준 스레드라고 부릅니다.

운영체제 위에서 동작하는 소프트웨어 계층에서 구현한 스레드는 그린 스레드라고 부릅니다.

어떤 부분에선 그린 스레드가 빠르고, 어떤 부분에선 네이티브 스레드가 빠르지만, 그린 스레드는 멀티코어를 활용할 수는 없으며, 동기 입출력(blocking I/O, synchronous I/O)을 구현하기 어렵습니다.

동시에 동작 가능한 스레드는 컴퓨터의 CPU 코어 개수로 결정됩니다. (논리 코어가 존재한다면 논리코어도 포함합니다.) 이 스레드 이상의 스레드를 사용한다면, 운영체제는 각 스레드에 시간을 나눠주면서 여러 스레드를 돌아가면서 실행시킵니다.

위와 같은 방법은 운영체제에서 아무 때나 스레드 실행을 멈추고 다른 스레드를 실행시킬 수 있기 때문에 선점형 스레딩이라고 부릅니다. 반대로 협력형 모델도 존재합니다.

다른 스레드가 실행될 수 있도록 한 스레드를 멈추는 것을 문맥 전환(Context Switching)이라고 부릅니다.

시스템 스레드와 사용자 스레드

시스템 스레드는 시스템에서 생성하고 관리합니다. 애플리케이션의 첫 번째 스레드(메인 스레드)는 시스템 스레드입니다. 보통 이 스레드가 종료될 때 애플리케이션이 종료됩니다.

사용자 스레드는 메인 스레드에서 할 수 없거나 하면 안되는 작업을 해야할 때, 애플리케이션에서 명시적으로 생성하는 스레드입니다.

UI가 있는 애플리케이션은 스레드 사용에 주의해야합니다. 보통 이런 애플리케이션의 메인스레드는 이벤트 스레드라고 부르는데, 이벤트가 일어날 때까지 대기했다가 이벤트를 처리할 수 있도록 전달하는 역할을 합니다. 이벤트 스레드가 지체되면 반응이 느려지고, 최악의 경우 기기가 멈출 수 있기 때문에 조심해야합니다.

이런 방법을 예방할 수 있는 것이 시간이 걸릴 수 있는 작업을 처리할 때 따로 스레드를 만드는 것입니다. 이런 사용자 스레드에서는 이벤트 스레드에서 처리할 수 있는 이벤트를 큐에 집어넣어서 이벤트 스레드에 데이터를 보냅니다. 이렇게 하면 이벤트 스레드를 중단하고 데이터가 올 때 까지 기다리거나 지속적으로 폴링해서 자원을 낭비하지 않고도 데이터를 받을 수 있습니다.