Home [CS] Blocking, Non-Blocking vs Sync, Async
Post
Cancel

[CS] Blocking, Non-Blocking vs Sync, Async

서론

이 두 개념은 얼핏보면 비슷하지만, 작업 처리를 바라보는 관점이 다릅니다.

Blocking과 Non-Blocking은 작업을 요청한 곳에서 다른 일을 할 수 있느냐가 중요한 포인트입니다.

Sync와 Async는 여러 작업을 요청했을 때 작업들이 어떤 순서로 처리되는지가 포인트입니다.

Blocking, Non-Blocking

이 개념은 호출자의 제어권과 관련이 있습니다.

결과가 처리될 때 까지 리턴되지 않고 기다려야한다면 blocking

결과가 처리되기 전에 리턴되어서 다른 일을 할 수 있다면 non-blocking

프로그래밍 언어에서 함수나 메서드를 사용할 때를 생각해볼게요. 함수가 결과를 리턴할때까지 thread가 blocking되는 함수가 있는 반면, 결과를 받기도 전에 바로 리턴되는 함수가 있습니다. 이런 함수들을 blocking, non-blocking함수라고 부르죠. 이처럼 프로그램 흐름과 좀 더 밀접한 관련이 있는 개념입니다.

Blocking

  • 작업이 끝날 때 까지 제어권을 반환하지 않으므로, 작업들이 순차적으로 수행된다.
  • 호출한 곳에서는 작업이 끝날 때 까지 대기해야한다. 즉 다른 작업을 못한다.

Non-Blocking

  • 작업이 끝나기도 전에 바로 제어권을 반환하므로, 호출한 곳에서 다음 작업을 수행할 수 있다.
  • 즉 작업이 진행되는 동안 호출한 곳에서는 다른 작업을 할 수 있다.

Synchronous, Asynchronous

이 개념은 작업들의 처리 순서와 관련이 있습니다.

여러 작업들을 순차적으로 수행한다면 synchronous

여러 작업들을 수행하면서 남는 시간에 다른 작업들을 동시에 수행한다면 asynchronous

Synchronous

  • 여러 요청이 들어온다면, 순차적으로 처리됩니다.
  • 일반적으로 호출한 곳에서 결과를 받아서 처리합니다.
  • 함수로 생각해보면, 디스크 읽기 등을 요청하고 그 함수내에서 디스크를 읽은 결과를 받아 처리합니다.

Asynchronous

  • 여러 요청이 들어온다면, 비동기적으로 처리되며 처리 순서가 보장되지 않습니다.
  • 일반적으로 호출한 곳에서 결과를 처리하는 게 아니라, 작업이 완료되었을 때 메시지(callback, event 등)를 받아 다른 곳에서 처리합니다.
  • 다른 곳에서 처리한다고 표현했지만, 이건 단순 코드 위치를 말하는 것이 아닙니다. callback같은 경우에는 함수 내부에 정의될 수도 있지만, 실제 실행되는 시점은 함수가 실행되는 시점과 다를 수 있습니다.

Asynchronous의 모호함

사실 이 개념은 명확하게 정의하기 어렵습니다. 문맥에 따라서 asynchronous가 다양하게 해석되기 때문이에요.

예를 들어 느린 작업의 대표격인 IO작업을 생각해볼게요. IO작업은 CPU를 거의 사용하지않고 io에 의존합니다. 그래서 만약 synchronous하게 IO가 포함된 작업을 수행하면 중간에 CPU가 노는 시간이 생깁니다. synchronous하므로 이 작업이 끝날때 까지 다음 작업은 수행되지 않을 것이고, 이 시간동안에는 CPU가 아무런 일도 하지 않아요. (정확히는 single-core환경에서)

그래서 이 문제를 개선하고자 asynchronous를 도입해보면, IO작업할 때는 CPU가 놀고있으니까 이 잠깐 비는 시간동안 다른 작업을 하는 것이죠. 그러면 최대한 CPU를 활용할 수 있겠죠? 이런 IO작업에서는 event나 callback을 통해서 완료되었음을 알립니다. IO작업에서의 asynchronous는 이런 event나 callback을 통해 구현됩니다.

그리고 MSA 환경을 생각해볼게요. 서버들이 서로 sync하게 통신한다고 가정해보면, 자칫 하나의 서버에 장애가 발생하면 다른 서버로 쉽게 전이될 수 있어요. 하지만 async하게 통신한다면 중간에 메시지 큐(or kafka)등을 사용해서 데이터를 주고받게되겠죠. 이 경우에는 서로 메시지로 요청을 보내고 나중에 다시 메시지를 통해 결과를 처리하는 방식이므로 받는 쪽에서 잘 처리해준다면 장애가 전파되지 않습니다.

이렇게 다양한 환경에서 async라는 용어가 사용되고있고, 문맥에 따라서 의미가 약간 달라질 수 있습니다.

Asynchronous와 non-blocking의 관계

Asynchronous는 어떻게 하면 여러 작업을 동시에 수행할 수 있을지에 관한 개념이에요. 이 Asynchronous를 구현하기 위해 multi-threading이나 non-blocking이 사용됩니다.

non-blocking을 사용하면 함수가 작업이 끝날때까지 대기하지 않으므로, 동시에 여러 작업을 수행할 수도 있겠죠? 정확히는 이 경우 CPU가 혼자 동시에 여러 작업을 수행한다기보다는, IO장비와 CPU가 서로 각자의 작업을 수행한다고 보는게 맞습니다. 아래에서 좀 더 자세하게 설명하겠습니다.

Asynchronous와 Multi-threading의 관계

Asynchronous는 보통 callback의 형태로 non-blocking과 많이 조합되어 사용됩니다. 그래서 마치 여러 작업들을 동시에 처리하는 것 처럼 보입니다.

하지만 multi-threading와는 다른 개념입니다. Asynchronous는 작업을 처리하는 방법에 관한 개념입니다. 그에 비해 multi-threading는 실제 작업을 처리하는 worker에 관한 개념입니다.

Asynchronous는 single, multi-threading 환경 어디에서든 적용될 수 있습니다. 요리로 예시를 들어볼게요.

Asynchronous, single-threaded

  1. 달걀을 굽는다.
  2. 달걀이 구워질 동안 식빵을 토스터기에 넣는다.
  3. 달걀과 식빵이 다 될동안 식기를 준비한다.

위의 예시에서 아침 준비하는 사람은 저 혼자뿐입니다. 즉 thread는 1개지만, 작업 중간중간 텀이 생길때 마다 다른 작업을 처리하죠.

Asynchronous, multi-threaded

  1. 나는 달걀을 굽는다.
  2. 나는 식빵을 토스터기에 넣는다.
  3. 친구는 식기를 준비한다.

이제 아침 준비 하는 사람이 2명으로 늘었습니다. 그래서 혼자할 때보다 일손이 좀 줄었습니다. 그래도 나는 여전히 해야할 작업이 2개니까 작업하면서 텀이 있을 때 다른 작업을 처리(async)합니다.

이렇게 multi-threading는 작업을 처리하는 worker와 관련있는 개념이고, asynchronous는 손(worker)이 놀고있지 않게 최대한 활용해보려는 개념입니다.

This post is licensed under CC BY 4.0 by the author.

[Spring] API서버 Error Handling 전략

[CS] 프레임워크와 라이브러리