Polymor!

[네트워크] 비동기와 동기 그리고 멀티 쓰레드에 관한 이야기. 본문

Web

[네트워크] 비동기와 동기 그리고 멀티 쓰레드에 관한 이야기.

Megan Kim 2020. 7. 28. 14:55

비동기, 동기, 블록, 넌블록.. 이런 이야기들을 한번쯤은 들어보았을텐데. 결론적으로만 말하면 이 개념들과 여러 조합들의 방식이 나온 것은 , I/O 를 효과적으로 처리하기 위해 나온 개념들이다. Read() , Write() 등과 같은 저 수준 시스템 콜을 하고 난 후 커널로 부터 응답을 받을 때까지 기다리지않고 제어권을 넘기는 넌 블록, Select()처럼 이벤트 기반으로 메세지를 날리는 걸 구현하기 위해 비동기의 방식이 나온 것이다. 이 배경을 이해한다면, 보편적으로 알고 있던 상황과는 다른 관점에서 이 개념들을 이해하기 수월하다. 

 

리눅스 I/O 모델

비동기란, 어떤 일련의 작업(예를들면 호출된 함수) 의 결과, 작업 종료(return) 등에 내 작업의 시작이 전혀 영향을 받지않을 때를  의미한다. Select 방식이 그렇다고 볼 수있다. 비동기적으로 Select 함수가 호출되었다~ 라는 표현을 생각하자. 

반면 동기란, 어떤 작업이 끝날 때까지(리턴 될때까지) 나는 '대기'하여야한다. 순차적으로 작업의 플로우에 영향을 주고 받는다. 

 

이와 다른 의미에서, 'Blocking' 과 'Non-Blocking' 개념이 있다. 비동기, 동기와는 개념적으로 다르나 추상적으로 비슷해보이니 주의하자.

Blocking은 작업이 A to Z 까지 다 마무리 될때까지 제어권을 넘기지않는다.  Non-blocking은 중간에 먼저 제어권은 넘길 수 있다. 

 

보통 우리가 익숙한 방식은 동기 + 블로킹 방식이다. 어떤 함수는 일을 끝낼 때까지 리턴을 하지않고(Blocking) 그 다음 작업들은 이 함수의 리턴  값이 올때까지 대기한다(Synchronous).

 

그렇다면 Non-blocking 과 동기의 조합은 어떨까? 난 제어권을 넘겼는데 쟤는 나의 결과를 기다린다.

 

 

위에 말한 Select 이벤트 기반의 방식은 아래와 같은 플로우로 Blocking(select) + Asynchronous 를 채택한다.

 

먼저, 쓰레드의 개념을 확실하게 해두고가자.

Thread는 프로세스 실행 단위이며, Process는 여러개의 Thread를 가질 수 있다.

하나의 프로세스를 구성하는 쓰레드들은 프로세스에 할당된 메모리, 자원 등을 공유한다.

 

단, Stack 영역은 공유되지않는다. 이는 멀티쓰레드가 비동기 방식을 채택하게 된 필연적 요소이다. 

참고적으로 Static 영역을 공유하여 전역 변수를 선언하여 여러 쓰레드가 값을 공유할 수 있으나, 이는 비동기 방식의 쓰레드를 고려하였을 때 효과적인 것인지는 많이 생각해보아야한다. 개인적인 생각으로는 가급적 사용하지않는 것이 좋다.

 

우리가 멀티 쓰레드 기반의 프로그램을 실행 시키게되면, 어떤 쓰레드가 먼저 실행될지는 예측 할 수 없다. 말 그대로 'MULTI'이기 때문에, 만약 쓰레드 간에 동기방식으로 돌아간다면, 그건 멀티 태스킹과는 거리가 먼 이야기 일 것이다. 따라서 쓰레드 '간'에는 비동기, 넌블록에 가깝고 쓰레드 '내'에서는 특수 경우를 제외하곤 블록+ 동기 방식이라고 생각하면 된다. 

 

 

* 비동기 스트리밍의 맥략을 살펴보자!

클라이언트 측에서 두가지 작업이 필요하다. 하나는 영상을 수신하는 작업이고 다른 하나는 영상을 재생하는 작업이다. 

영상을 '수신'하는 것은 Read I/O 이니 사실상 CPU 리소스를 크게 사용치 않는다. 반면 '재생'하는 작업엔 CPU가 소모될 것.

 

동기식으로 스트리밍을 한다면, 수신을 다 완료할때까지 재생을 할 수없다는 식이다. 이때 수신(Read)가 Blocking이면 커널에서 응답을 받을때까지 해당 어플리케이션 프로세스가 Sleep상태로 대기할 것이고, Non-Blocking이면 데이터를 다 받을때까지 계속 시스템콜을 보내면서 CPU리소스는 리소스대로, 어플리케이션은 그것대로 대기하는 식이다. 

 

비동기식이라면, 싱글쓰레드(Select,Poll)든, 멀티쓰레드로서든 어쨌든 앱 프로세스가 영상 '수신'을 무한정 '대기'하지않고 받으면서 그때그때 재생도 하며 CPU가 멀티태스킹하게 하는 개념이라고 생각하면 된다. 

 

Comments