동기와 비동기, 블로킹과 논블로킹

Hyunjun Jang·2021년 10월 23일
1

Synchronous/Asynchronous(동기/비동기)

Synchronous의 Syn는 together이란 뜻이고, chrono는 time이다. 따라서 Synchronous는 함께 시간을 맞춘다라는 뜻으로 해석된다. 반면에 Asynchronous는 앞에 A라는 접두사가 붙어 부정하는 형태가 되어 시간을 맞추지 않는 것이라 해석할 수 있다.

  • Synchronous
    동기는 두 가지 이상의 대상(함수, 애플리케이션 등)이 서로 시간을 맞춰 행동하는 것이다. 예를들어 호출한 함수가 호출된 함수의 작업이 끝나서 결과값을 반화하기를 기다리거나, 지속적으로 호출된 함수에게 확인 요청을하는 경우가 있다.

    어떤 대상 A와 B가 있을 때 동기적으로 처리하는 방법 두 가지를 살펴보자.

    A와 B가 시작 시간 또는 종료 시간이 일치하면 동기이다. 예를 들어

    A, B 쓰레드가 동시에 작업을 시작하는 경우 (예를 들면 자바에서 CyclicBarrier)
    메서드 리턴 시간(A)과 결과를 전달받는 시간(B)이 일치하는 경우

    A가 끝나는 시간과 B가 시작하는 시간이 같으면 동기이다. 예를 들어 자바에서 synchronizedBlockingQueue가 위와 같은 경우이다.

    호출된 함수의 리턴하는 시간과 결과를 반환하는 시간이 일치하는 경우

  • Asynchronous
    비동기는 동기와 반대로 대상이 서로 시간을 맞추지 않는 것을 말한다. 예를 들어 호출하는 함수가 호출되는 함수에게 작업을 맡겨놓고 신경을 쓰지 않는 것을 말한다.

    호출된 함수의 리턴하는 시간과 결과를 반환하는 시간이 일치하지 않는 경우

Blocking/NonBlocking

블록킹/논블록킹동기/비동기와 같이 생각하는 경우가 많은데, 이는 서로 관점이 다르다. 블록킹/논블록킹은 직접 제어할 수 없는 대상을 처리하는 방법에 따라 나눈다. 직접 제어할 수 없는 대상은 대표적으로 IO, 멀티쓰레드 동기화가 있다.

  • 호출된 함수가 바로 리턴해서 호출한 함수에게 제어권을 넘겨주고, 호출한 함수가 다른 일을 할 수 있는 기회를 줄 수 있으면 NonBlocking이다.
  • 호출된 함수가 자신의 작업을 모두 마칠 때까지 호출한 함수에게 제어권을 넘겨주지 않고 대기하게 만든다면 Blocking이다.

호출되는 대상이 직접 제어할 수 없는 경우 이를 구분할 수 있다.

  • Blocking
    Blocking은 직접 제어할 수 없는 대상의 작업이 끝날 때까지 제어권을 넘겨주지 않는 것이다. 예를 들어 호출하는 함수가 IO를 요청했을 때 IO처리가 완료될 때까지 아무 일도 하지 못한 채 기다리는 것을 말한다.

    직접 제어할 수 없는 대상의 작업이 끝날 때까지 기다려야 하는 경우

  • Non-Blocking
    Non-Blocking은 Blocking과 반대되는 개념이다. 직접 제어할 수 없는 대상의 작업 처리 여부와 상관이 없다. 예를 들어 호출하는 함수가 IO를 요청한 후 IO처리 완료 여부와 상관없이 바로 자신의 작업을 할 수 있다.

    직접 제어할 수 없는 대상의 작업이 완료되기 전에 제어권을 넘겨주는 경우

NonBlocking-Sync

NonBlocking 메서드 호출 후 바로 반환 받아서 다른 작업을 할 수 있게 되지만, 메서드 호출에 의해 수행되는 작업이 완료된 것은 아니며, 호출하는 메서드가 호출되는 메서드 쪽에 작업 완료 여부를 계속 문의한다.

NonBlocking-Sync 처리 예로 future.isDone() 가 있다.

 Future ft = asyncFileChannel.read(~~~);
while(!ft.isDone()) {
    // isDone()은 asyncChannle.read() 작업이 완료되지 않았다면 false를 바로 리턴해준다.
    // isDone()은 물어보면 대답을 해줄 뿐 작업 완료를 스스로 신경쓰지 않고,
    //     isDone()을 호출하는 쪽에서 계속 isDone()을 호출하면서 작업 완료를 신경쓴다.
    // asyncChannle.read()이 완료되지 않아도 여기에서 다른 작업 수행 가능
// 작업이 완료되면 작업 결과에 따른 다른 작업 처리
// 실무에서는 CompletableFuture를 쓰거나,
// Future를 쓴다면 위의 while 블록은 별도의 쓰레드로 빼서 실행하는 것이 좋다

Blocking-Async

앞에서 살펴본대로 조합해보면 Blocking-Async는 호출되는 함수가 바로 리턴하지 않고, 호출하는 함수는 작업 완료 여부를 신경쓰지 않는 것이다.

작업 끝날 때까지 기다렸다가 결과를 반환 받아서 처리하는 Blocking-Sync 방식과 성능적으로 거의 차이가 나지 않을 것 같은 방식이다.

Blocking-Async는 별로 이점이 없어서 일부러 이 방식을 사용할 필요가 없기는 한데, 의도하지 않게 Blocking-Async로 동작하는 경우가 있다고 한다.

Blocking-Async의 대표적인 케이스

  • Node.js에서 Async(비동기)로 진행해도, db작업 호출시 MySQL에서 제공하는 드라이버 호출, 이것은 blocking방식
  • Java의 Servlet(멀티 쓰레드 기반) + JDBC

Blocking-Async는 별다른 장점이 없어서 일부러 사용할 필요는 없지만,

NonBlocking-Async 방식을 쓰는데 그 과정 중에 하나라도 Blocking으로 동작하는 놈이 포함되어 있다면 의도하지 않게 Blocking-Async로 동작할 수 있다.

NonBlocking-Async

성능과 자원의 효율적 사용 관점에서 가장 유리한 모델은 Async-NonBlocking 모델이다.

정리

  • Synchronous/Asynchronous는 호출되는 함수의 작업 완료 여부를 누가 신경쓰냐가 관심사다. 결과값에 반환 여부의 차이이다.
    • 호출된 함수의 수행 결과 및 종료를 호출한 함수가(호출된 함수뿐 아니라 호출한 함수도 함께 신경 쓰면 Synchronous
    • 호출된 함수의 수행 결과 및 종료를 호출된 함수 혼자 직접 신경 쓰고 처리한다면(as a callback fn.) Asynchronous
  • Blocking/NonBlocking은 호출되는 함수가 바로 리턴하느냐 마느냐가 관심사다. 제어권에 대해 통제하는 방법의 차이라고 할수 있다.
    • 호출된 함수가 자신이 할 일을 모두 마칠 때까지 제어권을 계속 가지고서 호출한 함수에게 바로 돌려주지 않으면 Block
    • 호출된 함수가 자신이 할 일을 채 마치지 않았더라도 바로 제어권을 건네주어(return) 호출한 함수가 다른 일을 진행할 수 있도록 해주면 Non-block

Reference

https://velog.io/@codemcd/Sync-VS-Async-Blocking-VS-Non-Blocking-sak6d01fhx
https://heecheolman.tistory.com/48
http://homoefficio.github.io/2017/02/19/Blocking-NonBlocking-Synchronous-Asynchronous/
https://programming119.tistory.com/238

profile
Let's grow together😊

0개의 댓글