CS 스터디 - Blocking / Non-blocking & Synchronous / Asynchronous

또리·2024년 1월 22일
1

CS-STUDY

목록 보기
1/2
post-thumbnail

Blocking / Non-blocking

Blocking / Non-Blocking은 호출된 함수가 바로 return하여 호출한 함수에게 제어권을 넘겨주는지에 대해 관점을 둔다.

함수 A, B가 있고 A 안에서 B를 호출했다고 가정해보자. 이 때 호출한 함수는 A고, 호출된 함수는 B가 된다.

현재 제어권이 B에게 주어졌고, B는 자신의 일을 진행해야 한다.

  • Blocking : 함수 B는 종료될 때 까지 제어권을 가지고 있는다. 함수 A는 B가 종료될 때 까지 기다려야 한다.
    (A 함수는 B 함수가 실행되는 동안 제어권이 없으므로 B 함수의 종료를 기다린다.)
  • Non-blocking : 함수 B는 호출됨과 동시에 바로 리턴하여 함수 A에게 제어권을 바로 넘겨준다. A는 B를 기다리면서도 다른 일을 진행할 수 있다.

즉, 호출된 함수에서 일을 시작할 때 바로 제어권을 리턴해주냐, 할 일을 마치고 리턴해주느냐에 따라 Blocking과 Non-blocking으로 나누어진다고 볼 수 있다.

Synchronous / Asynchronous

Synchronous / Asynchronous는 호출되는 함수의 작업 완료 여부를 누가 신경쓰는지에 대해 관점을 둔다.

함수 A, B가 있고 A 안에서 B를 호출했다고 가정했을 때, B의 수행 결과나 종료 상태를 A가 신경쓰고 있는지의 유무의 차이이다.

  • Synchoronous : 함수 A가 함수 B를 호출하면, 함수 B의 결과를 함수 A가 처리하는 것이다. 이는 작업 요청에 대한 결과값을 직접 받는 것이다. 그래서 결과 값과 return 값이 동일하다.

  • Asynchronous : 함수 A가 함수 B를 호출하면, 함수 B의 결과를 함수 B가 처리하는 것이다. 이는 함수 A가 함수 B의 작업을 시작시키고, 완료를 기다리지 않고 다른 일을 처리할 수 있게 된다. 그래서 결과 값과 return 값이 동일하지 않을 수도 있다.
    (호출되는 함수에게 callback을 전달해서, 호출되는 함수의 작업이 완료되면 호출되는 함수가 전달받은 callback을 실행하고, 호출하는 함수는 작업 완료 여부를 신경쓰지 않는다.)

Blocking + Synchronous & Non-Blocking + Asynchronous

Blocking + Synchronous (Sync Blocking)

  • 다른 작업이 진행되는 동안 자신의 작업을 처리하지 않고(Blocking), 다른 작업의 완료 여부를 바로 받아 순차적으로 처리(Synchronous) 방식이다. 다른 작업의 결과가 자신의 작업에 영향을 주는 경우에 활용할 수 있다.
  • 위의 이미지에서, Blocking이기 때문에 호출한 시점에서부터는 파란색 task는 다른 일을 하지 못하고 대기해야 한다. 대기가 끝나면 Synchronous이기 때문에 파란색 task가 초록색 task의 return 값을 받아 결과값으로 반환한다.
  • 대표적인 예로 파일을 읽어 내용을 처리하는 로직을 들 수 있다. 파일을 먼저 읽어야 그 다음 작업을 처리할 수 있기 때문이다.
  • 이러한 방식은 코드가 순차적으로 실행되는 특성을 가지고 있다. 일반적으로 작업이 간단하거나 작업량이 적은 경우에 사용된다. 작업량이 많거나 시간이 오래 걸리는 작업을 처리해야 하는 경우에는 독이 되는데, 하나의 작업이 끝날 때까지 다른 작업을 처리하지 못하므로 전체 처리 시간이 오래 걸리게 되어 비효율적이기 때문이다. 이러한 경우에는 Async Non-blocking 방식을 사용하여 작업을 처리하는 것이 좋다.

Non-blocking + Asynchronous (Async Non-blocking)

  • 다른 작업이 진행되는 동안에도 자신의 작업을 처리하고(Non-blocking), 다른 작업의 결과를 바로 처리하지 않아 작업 순서가 지켜지지 않는(Async) 방식이다. 다른 작업의 결과가 자신의 작업에 영향을 주지 않은 경우에 활용할 수 있다.
  • 위의 이미지에서, Non-blocking이기 때문에 호출을 해도 파란색 task는 다른 일을 수행할 수 있다. Asynchronous이기 때문에 초록색 task가 수행을 완료하면 callback을 통해 return 값을 별도로 전달한다.
  • 파일 읽기 프로그램을 Async Non-blocking 방식으로도 코드를 구현할 수 있다. Sync Blocking 방식과 두드러진 차이점은 호출 함수에 콜백 함수를 넣었다는 점이다. 이를 통해 Async Non-blocking 방식대로 처리된 작업의 결과를 후처리 할 수 있게 된다.
  • 또한 비동기이기 때문에 작업의 순서를 고려하지 않아 결과가 순차적으로 나타나지 않을 수 있다.
  • 이처럼 Async Non-blocking 조합은 작업량이 많거나 시간이 오래 걸리는 작업을 처리해야 하는 경우에 적합하다. 예를 들어, 대용량 데이터를 처리하거나 많은 요청을 처리하는 서비스에서는 Async Non-blocking 방식을 사용하여 한 작업이 처리되는 동안 다른 작업을 처리할 수 있으므로 전체 처리 시간을 줄일 수 있어 애플리케이션 처리 성능을 향상시킬 수 있게 된다.
  • 성능과 자원의 효율적 사용 관점에서 가장 유리한 모델은 Async Non-blocking 방식이다.

Non-blocking + Synchronous (Sync Non-blocking)

  • 다른 작업이 진행되는 동안에도 자신의 작업을 처리하고(Non-blocking), 다른 작업의 결과를 바로 처리하여 작업을 순차대로 수행하는(Synchronous) 방식이다.
  • 위의 이미지에서, Non-blocking이기 때문에 호출을 해도 파란색 task는 다른 일을 수행할 수 있다. 그러나 Synchronous이기 때문에 파란색 task가 초록색 task의 return 값을 받아 결과 값으로 반환해야 한다. 그러나 초록색 task의 종료 시점을 모르기 때문에 반복적으로 완료 확인을 하고, 완료가 확인되면 이 값을 결과 값으로 반환한다.
  • 스레드(Thread) 객체를 만들어 요청 작업을 백그라운드에서 돌게 하고 메인 메서드에서 while문을 통해 스레드가 모두 처리되었는지 끊임없이 확인하고, 처리가 완료되면 다음 메인 작업을 수행하는 경우를 예로 들 수 있다.
// Runnable 인터페이스를 구현하는 클래스 정의
class MyTask implements Runnable {
    @Override
    public void run() {
        // 비동기로 실행할 작업
        System.out.println("Hello from a thread!");
    }
}

public class Main {
    public static void main(String[] args) {
        // Thread 객체 생성
        Thread thread = new Thread(new MyTask());

        // 스레드 실행
        thread.start();

        // Non-Blocking이므로 다른 작업 계속 가능
        System.out.println("Main thread is running...");

        // Sync를 위해 스레드의 작업 완료 여부 확인
        while (thread.isAlive()) {
            System.out.println("Waiting for the thread to finish...");
        }
        System.out.println("Thread finished!");
        
        System.out.println("Run the next tasks");
    }
}

  • 스레드를 이용하여 작업을 병렬적으로 처리하도록 지시했지만, 메인 코드의 while 문을 수행함으로써 요청한 작업의 완료 여부를 계속 확인하고, 결과적으로 결국 동기적으로 작업이 순서대로 수행됨을 볼 수 있다.

Blocking + Asynchronous (Async Blocking)

  • 다른 작업이 진행되는 동안 자신의 작업을 멈추고(Blocking), 다른 작업의 결과를 바로 처리하지 않아 순서대로 작업을 수행하지 않는(Asynchronous) 방식이다.
  • 위의 이미지에서, Blocking이기 때문에 호출한 시점에서부터는 파란색 task는 다른 일을 하지 못하고 대기해야 한다. Asynchronous이기 때문에 초록색 task는 자신의 종료를 자신이 처리하고, callback을 호출하면, 파란색 task가 다른 일을 수행할 수 있게 된다.
  • Async Blocking 방식은 실무에서 마주하기 쉽지 않아 다룰 일이 거의 없다.
  • 대표적인 사례로는 Node.js + MySQL의 조합인데, Node.js에서 비동기 방식으로 데이터베이스에 접근하기 때문에 Asynchronous이지만, 데이터베이스에 접근하기 위한 MySQL 드라이버가 Blocking 방식으로 작동된다.
  1. JavaScript는 비동기 방식으로 MySQL에 쿼리를 보낸다. (Async)
  2. MySQL은 쿼리를 처리하면서 JavaScript에게 제어권을 넘겨주지 않는다. (Blocking)
  3. 그러면 JavaScript는 다른 작업을 계속 수행할 수 있지만, MySQL의 결과값을 필요로 하기 때문에 MySQL이 쿼리를 완료할 때까지 기다려야 한다.
  4. 결국 Sync Blocking와 작업 수행에 차이가 없게 된다.
  • 이렇게 Node.js + MySQL 조합이 Async Blocking 조합이라고 할 수 있다. 하지만 이러한 조합은 오히려 혼동을 일으키기 때문에 실무에서는 Node.js 서버 프로그래밍을 할 때 async/await로 동기 처리를 하는 편이라고 한다.

참고

링크
링크
링크

profile
Backend Developer

0개의 댓글

관련 채용 정보