[CS] Blocking/Non-Blocking, 동기와 비동기

이준기·2022년 8월 4일
0

Blocking / Non-Blocking


주로 멀티 스레드, I/O 등에서 사용되는 개념이며, 함수의 리턴 시점 및 제어권이 관심사다.

→ 어떠한 작업이 진행중일때 다른 작업을 동시에 진행할 수 있냐 ?

Blocking

  • 제어권이 호출된 함수에게 넘어가서 호출된 함수 내에서 작업이 모두 끝난 후 호출한 함수에게 다시 제어권이 넘어온다.
  • 작업이 완료된 후에야 새로운 작업을 수행할 수 있다.
  • ex. Spring Boot는 Block I/O + 멀티 쓰레드

Non-Blocking

  • 제어권이 계속 호출한 함수에 있기 때문에 작업의 완료여부와 관계없이 새로운 작업을 수행할 수 있다.
  • ex. Node.js는 Non-Block I/O + 싱글 쓰레드

Synchronous / Asynchronous


주로 어플리케이션에서 자주 다뤄지는 개념이며, 다음 작업이 요청되는 시간이 관심사다.

→ 프로세스 간 작업의 흐름이 순차적이냐 ?

Synchronous(동기)

  • 현재 작업의 응답이 끝남과 동시에 다음 작업이 요청된다.
  • 함수를 호출하는 곳에서 호출되는 함수가 결과를 반환할 때까지 기다린다.
  • 그렇기 때문에 작업 완료 여부를 계속해서 확인한다.

Asynchronous(비동기)

  • 현재 작업의 응답이 끝나지 않은 상태에서도 다음 작업이 요청된다.
  • 함수를 호출하는 곳에서 결과를 기다리지 않고, 다른 함수(callback)에서 결과를 처리한다.
  • 그렇기 때문에 작업 완료 여부를 계속해서 확인하지 않는다.

Blocking vs Synchronous ??


그래서 뭐가 다른거야???

상위 프로세스 boss 함수와 하위 프로세스 employee 함수로 예를 들어 보자.

Synchronous(동기) + Blocking

function employee () {
  for (let i = 1; i < 101; i++) {
    console.log(`직원: 인형 눈알 붙히기 ${i}번 수행`);
  }
}

function boss () {
  console.log('사장: 출근');
  employee();
  console.log('사장: 퇴근');
}

boss();
사장: 출근
직원: 인형 눈알 붙히기 1번 수행
직원: 인형 눈알 붙히기 2번 수행
...
직원: 인형 눈알 붙히기 100번 수행
사장: 퇴근
  • 동기 방식이기 때문에 작업의 흐름이 순차적으로 진행되는 것이 보장된다.
  • 블로킹 방식이기 때문에 어떠한 작업이 진행중일때는 다른 작업을 동시에 진행할 수 없다.

Synchronous(동기) + Non-Blocking

function* employee () {
  for (let i = 1; i < 101; i++) {
    console.log(`직원: 인형 눈알 붙히기 ${i}번 수행`);
    yield;
  }
  return;
}

function boss () {
  console.log('사장: 출근');

  const generator = employee();
  let result = {};

  while (!result.done) {
    result = generator.next();
    console.log(`사장: 유튜브 시청...`);
  }

  console.log('사장: 퇴근');
}

boss();
사장: 출근
직원: 인형 깔알 붙히기 1번 수행
사장: 유튜브 시청...
직원: 인형 눈알 붙히기 2번 수행
사장: 유튜브 시청...
...
직원: 인형 눈알 붙히기 100번 수행
사장: 유튜브 시청...
사장: 퇴근

JavaScript의 제너레이터를 사용하여, 작업의 순서를 지키면서도 상위 프로세스(boss)가 다른 작업을 하도록 만들었다.

  • 동기 방식이기 때문에 작업의 흐름이 순차적으로 진행되는 것이 보장된다.
  • 논블로킹 방식이기 때문에 어떠한 작업이 진행중이어도 다른 작업을 수행할 수 있다.

Asynchronous(비동기) + Non-Blocking

function employee (maxDollCount = 1, callback) {
  let dollCount = 0;
  const interval = setInterval(() => {
    if (dollCount > maxDollCount) {
      callback();
      clearInterval(interval);
    }
    dollCount++;
    console.log(`직원: 인형 눈알 붙히기 ${dollCount}번 수행`);
  }, 10);
}

function boss () {
  console.log('사장: 출근');
  employee(100, () => console.log('직원: 눈알 결산 보고'));
  console.log('사장: 퇴근');
}

boss();
사장: 출근
사장: 퇴근
직원: 인형 눈알 붙히기 1번 수행
직원: 인형 눈알 붙히기 2번 수행
...
직원: 인형 눈알 붙히기 100번 수행
직원: 눈알 결산 보고

사장은 직원이 일이 끝나기도 전에 퇴근해버렸다. 그 후 직원의 일이 끝나고, 사장에게 보고했다.

  • 비동기 방식이기 때문에 작업의 흐름이 순차적으로 진행되는 것을 보장하지 않는다. → 상위 프로세스(boss)는 하위 프로세스(employee)의 작업이 언제 끝나는지 관심 없음
  • 논블로킹 방식이기 때문에 어떠한 작업이 진행중이어도 다른 작업을 수행할 수 있다.

비동기 & 논블로킹 방식은 여러 개의 작업을 동시에 처리할 수 있는 부분에서 효율적이라고 할 수 있지만, 너무 복잡하게 얽힌 비동기 처리 때문에 개발자가 어플리케이션의 흐름을 읽기 어려워지는 등의 문제가 있을 수 있다. JavaScript에서 Promise나 async/await와 같은 문법을 사용하는 이유도 이런 비동기 처리의 흐름을 좀 더 명확하게 인지하고자 하는 노력인 것이다.

Asynchronous(비동기) + Blocking

일반적으로 어플리케이션 레이어에서 자주 사용되지 않기도 하고, 평소에 접하기 힘든 개념이라고 한다.

이 방식은 블록킹 방식으로 진행되기 때문에 개발자에게도 직관적으로 다가오고, 비동기 방식이기 때문에 여러 개의 I/O를 동시에 감시하며 처리할 수 있다. 하지만 성능이 그렇게 좋은 편은 아니므로 IBM에서는 높은 성능이 필요한 어플리케이션에서는 되도록 쓰지 말라고 한다.

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

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

Reference


https://cotak.tistory.com/136

https://evan-moon.github.io/2019/09/19/sync-async-blocking-non-blocking/#동기-방식--논블록킹-방식

profile
Hongik CE

0개의 댓글