동기 vs 비동기 (feat. blocking vs non-blocking)

이원희·2020년 11월 10일
38

✍️ etc

목록 보기
2/4
post-thumbnail

동기와 비동기... 굉장히 많이 나오는 주제이고, 개발하다보면 많이 들리는 얘기이다.
(물론 중요한 개념인 것도 맞고)
동기/비동기, blocking/non-blocking 굉장히 헷갈린다. (나도 엄청 헷갈렸고 많이 혼용해서 사용했음...)

전에 GCD에 대해 공부하면서 명확하게 알고 있을 필요가 있어 공부해뒀었는데 글로 남겨두려고 한다.
(GCD도 포스팅해야지... 왜케 자꾸 포스팅할 것이 많아질까..)


동기(Synchronous) vs 비동기(Asynchronous)

네트워크 코드를 작성하면서 동기/비동기에 대해서 더 많이 접했던거 같다.

동기(Synchronous)

  • Thread1이 작업을 시작 시키고, Task1이 끝날때까지 기다렸다 Task2를 시작한다.
  • 작업 요청을 했을 때 요청의 결과값(return)을 직접 받는 것이다.
  • 요청의 결과값이 return값과 동일하다.
  • 호출한 함수가 작업 완료를 신경 쓴다.

비동기(Asynchronous)

  • Thread1이 작업을 시작 시키고, 완료를 기다리지 않고, Thread1은 다른 일을 처리할 수 있다.
  • 작업 요청을 했을 때 요청의 결과값(return)을 간접적으로 받는 것이다.
  • 요청의 결과값이 return값과 다를 수 있다.
  • 해당 요청 작업은 별도의 스레드에서 실행하게 된다.
  • 콜백을 통한 처리가 비동기 처리라고 할 수 있다.
  • 호출된 함수(callback 함수)가 작업 완료를 신경 쓴다.

blocking vs non-blocking

blocking과 non-blocking은 주로 IO의 읽기, 쓰기에서 사용된다.

blocking

  • 요청한 작업을 마칠 때까지 계속 대기한다.
  • 즉시 return한다.
  • return 값을 받아야 끝난다.
  • Thread 관점으로 본다면, 요청한 작업을 마칠 때까지 계속 대기하며 return 값을 받을 때까지 한 Thread를 계속 사용/대기 한다.

non-blocking

  • 요청한 작업을 즉시 마칠 수 없다면 즉시 return한다.
  • 즉시 리턴하지 않는다. (일을 못하게 막는다.)
  • Thread 관점으로 본다면, 하나의 Thread가 여러 개의 IO를 처리 가능하다.

동기/비동기, blocking/non-blocking의 차이는?

사실 이렇게만 보면 동기랑 blocking이 비슷하고, 비동기랑 non-blocking이 비슷해보인다.
동기/비동기, blocking/non-blocking 두 그룹의 차이는 관심사가 다르다.

blocking/non-blocking

이 그룹은 호출되는 함수가 바로 return하느냐 마느냐가 관심사이다.

호출된 함수가 바로 return해서 호출한 함수에게 제어권을 넘겨주고
호출한 함수가 다른 일을 할 수 있는 기회를 줄 수 있으면 non-blocking이다.

호출된 함수가 자신의 작업을 모두 마칠 때까지
호출한 함수에게 제어권을 넘겨주지 않고 대기하게 만든다면 blocking이다.

동기/비동기

이 그룹은 호출되는 함수의 작업 완료 여부를 누가 신경쓰느냐가 관심사이다.

호출되는 함수에게 callback을 전달해서 호출되는 함수의 작업이 완료되면
호출되는 함수가 전달받은 callback을 실행하고, 호출한 함수는 작업 완료 여부를 신경쓰지 않는다면 비동기이다.

호출하는 함수가 호출되는 함수의 작업 완료 후 return을 기다리거나
호출되는 함수로부터 바로 return 받더라도 작업 완료 여부를 호출한 함수 스스로 확인하며 신경 쓴다면 동기이다.

동기/비동기, blocking/non-blocking 조합

동기/비동기, blocking/non-blocking에 대해 공부하다보면 아래와 같은 그림과 자주 마주치게 된다.

blocking + Synchronous, non-blocking + Asynchronous

blocking + Synchronous

결과가 처리되어 나올때까지 기다렸다가 return 값으로 결과를 전달한다.

non-blocking + Asynchronous

작업 요청을 받아서 별도의 프로세서에서 진행하게 하고 바로 return(작업 끝)한다.
결과는 별도의 작업 후 간접적으로 전달(callback)한다.

non-blocking + Synchronous


결과가 없다면 바로 return한다.
결과가 있으면 바로 결과를 return 한다.
(결과가 생길때까지 계속 완료 되었는지 확인)

blocking + Asynchronous


호출되는 함수가 바로 return하지 않고, 호출하는 함수는 작업 완료 여부를 신경쓰지 않는다.
(이 조합은 사실 이점이 없어서 일부러 이 방식을 사용하진 않는다고 한다.)
(의도하지 않게 blocking+Async로 동작하는 경우가 있다고는 한다. 이는 non-blocking+Async를 추구하다 의도가 변질되어버림... 대표적으로 Node.js + MySQL 조합이라고 한다.)

예시랄까?

상황: 급하게 알아야 하는 답을 누군가에게 물어봐야하는 상황

  • 전화로 물어봐서 즉답을 얻는다. = 동기 요청처리
  • 이메일로 물어보고 메일 송신을 완료(return)했지만 답은 언제 올지 모른다. = 비동기 요청처리
  • 전화를 했는데 상대방이 너무 바빠 전화를 받지 않음
    전화를 받을때까지 계속 대기 = 동기 + 블록킹
  • 전화를 했는데 안 받음
    끊었다가 나중에 다시 전화함
    계속 반복했다가 어느 순간에 받아서 답을 얻음 = 동기 + 논블록킹

(이 영상이 이해하는데 도움이 될까해서 첨부해두겠다.)

3개의 댓글

comment-user-thumbnail
2021년 12월 19일

헷갈리는 개념인데 너무 잘 설명해주셔서 감사합니다 마지막 예시로 이해가 됐어요!

답글 달기
comment-user-thumbnail
2022년 4월 28일

블로킹 논블로킹 설명해주신 부분에 리턴에 대한 설명이 뒤바뀌어 있네요 수정부탁드립니다!

답글 달기
comment-user-thumbnail
2023년 2월 24일

non-blocking + Asynchronous 이라면 task1과 task2는 개념적으로 병렬로 또는 독립적으로 실행된다고 보면 되나요 ?

답글 달기