Post

async-sync-blocking-nonblocking

질문

1
동기와 비동기, 블로킹과 논블로킹의 차이를 설명하고 각 개념을 적용할 수 있는 사례가 뭐가 있을까?

설명 전에..

사전적 정의

  • 정보통신분야에서는 두 신호의 일치화에 쓰이는듯

동기, 同期, synchronization 주기적인 운동을 하는 개체들이 서로 영향을 주고받거나 받게 됨으로써, 동일한 주기를 갖게되는 것, 그러한 현상을 동기 현상(同期現狀)이라 하고, 동기된 상태를 동기화(同期化) 되었다고 한다, 통신에서는 주로 서로 다른 시스템이나 네트워크에서 클럭 주파수나 비트, 프레임, 워드 등을 일치시키는데 사용된다.

비동기, asynchronous 연관된 메시지가 연대순 및 절차적으로 분리되는 경우 비동기적인 상호 작용이라고 한다. 요청-응답의 상호 작용을 예로 들면, 클라이언트 에이전트는 미래의 불확실한 시점에서 응답을 처리할 수 있다. 이렇게 하기 위한 메커니즘에는 폴링, 다른 메시지 수신의 알림 등이 있다. 출처 : 단체표준 TTAS.KO-10.0179 웹서비스 용어

블로킹, blocking 데이터 신호의 전송이 끝나기 전에는 다음 동작을 진행할 수 없는 경우. 출처 : 단체표준 TTAK.OT-10.0288 시스템 수준 반도체 IP 인터페이스 모델링

논블로킹, non-blocking 데이터 신호의 전송이 끝나기 전에도 다음 동작을 진행할 수 있는 경우. 본 표준에서는 블로킹으로 별도 표기되지 않은 경우에는 모두 논블로킹으로 간주한다. 출처 : 단체표준 TTAK.OT-10.0288 시스템 수준 반도체 IP 인터페이스 모델링

본 포스트에서 설명하고자 하는 개념의 사전설정

  • 호출하는함수(caller)
  • 호출당하는함수(callee, 이하 ..ee로 작성)가 있음.

  • caller..ee를 호출했을 때, (..ee는 별도의 스레드(같은걸로)에서 실행 된다고 가정)
  • 함수 호출관점에서 동기와 비동기 && 블로킹과 논블로킹을 구분할 필요가 있음.

개념 분류 기준

블로킹(Blocking) | 논블로킹(Nonblocking)

  • ..ee를 호출한 함수caller의 다음 행동을 막는다(blocking) ? Y(블로킹) : N(논블로킹)
  • 그럼, caller..ee실행끝날때까지 대기탄다? Y(블로킹)
  • 즉, ..ee호출시점에 제어권..ee가 가지고 간다? Y(블로킹) : N(논블로킹)

  • 제어권 : 쉽게 얘기해서 내가 돌리는 앱의 다음 코드라인을 실행할지? 핸들링하는 주체 권한

서버 소켓의 관점에서

  • java.net.ServerSocket
    • accept() 의 처리 수행 기준 : 클라이언트의 연결요청이 생겼는가?
    • 클라이언트(caller)의 연결요청 없으면 accept() 의 수행이 멈춤(스레드가 블로킹됨)
      • 서버 동시 접속요청 하는 클라이언트 수가 증가할수록, 여러 클라이언트의 accept()요청을 처리해야함 : 수행속도 느려짐
      • 접속요청수가 서버 자원 임계점(힙메모리) 넘으면 OOM, 장애발생.
      • 장애발생은 막기위해 요청들의 병렬 처리 가능하도록 쓰레드풀로 블로킹 소켓 서버를 생성

동기(Sync) | 비동기(ASync)

  • caller..ee완료 여부를 체크하는지? Y(sync) : N(async)

    공통점

    ..ee 는 작업완료하면 콜백 호출함.

CASE

  • 4가지 케이스가 있겠다.

동기(Sync) - 블로킹(Blocking)

  • Sync니까, caller..ee에게 완료여부 체크 해야 하지만,
  • 제어권..ee에게 있으므로 완료여부 체크를 할 수 없음.
  • java main()으로 돌리는 여러 알고리즘 문제 코드들

동기(Sync) - 논블로킹(Nonblocking)

  • caller..ee완료여부체크(완료했니? 반복) 하면서 caller의 작업 돌고있음.
  • 게임 로딩화면
    • 화면 하나 띄워주고, 논블로킹으로 맵정보 불러오면서 완료여부 체크
    • 완료정도 % 형태로 화면에 갱신해줌
  • …외 논블로킹 방식의 여러 로그인 처리 로직들

비동기(ASync) - 논블로킹(Nonblocking)

  • caller..ee 의 완료여부 체크 안함.
  • ..ee는 끝나면 콜백으로 알려줄 뿐
  • 웹사이트들 (ajax)
    • 여러 asset파일들(img,js,…) 읽는작업 완료되면 콜백 실행(화면띄워줌) 하는 구조

비동기(ASync) - 블로킹(Blocking)

  • ..ee 가 제어권을 가지고 있음.
  • caller는 완료여부도 신경안씀, 콜백만 전달받아 실행할뿐
  • 동기-블로킹과 별 차이가 없다
  • 그래서 4가지 케이스 중 가장 끝에 놨음.

콜백


  • 적용 전
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    function findUser(id) {
    let user;
    setTimeout(function () {
      console.log("waited 0.1 sec.");
      user = {
        id: id,
        name: "User" + id,
        email: id + "@test.com",
      };
    }, 100);
    return user;
    }
    console.log('start');
    const user = findUser(1);
    console.log("user:", user);
    console.log('end');
    
  • 실행결과
    1
    2
    3
    4
    5
    
    $ node findUser.js
    start
    undefined
    end
    waited 0.1 sec.
    
  • findUser()를 리턴하기도 전에 메인의 console.log("user:", user)를 실행해버림.
  • 호출된 함수 setTimeout()은 별도로 빠져서 실행됨 nonblocking

  • 적용 후
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    function findUser(id, callback) {
    let user;
    setTimeout(function () {
      console.log("waited 0.1 sec.");
      user = {
        id: id,
        name: "User" + id,
        email: id + "@test.com",
      };
      callback(user);
    }, 100);
    return user;
    }
    console.log('start');
    const user = findUser(1, function(user) {
      console.log(user);
    });
    console.log('end, user:' + user);
    
  • 실행결과
    1
    2
    3
    4
    5
    
    $ node findUser.js
    start
    end, user:undefined
    waited 0.1 sec.
    { id: 1, name: 'User1', email: '1@test.com' }
    
  • 완료여부를 체크하지 않고, 완료되면 callback으로 알려줌

사족

  • 실행결과상 undefined가 신경쓰여 promise로 적용
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    function findUser(id) {
    let user;
    return new Promise((resolve, _) => {
      console.log("waited 0.1 sec.");
      setTimeout(() => {
        user = {
          id: id,
          name: "User" + id,
          email: id + "@test.com",
        };
        resolve(user)
      }, 1000)
    });
    }
    function userMapping(user) {
    return Object.entries(user).map(([k,v]) => (
      `${k}:${v}`
    ));
    }
    console.log('start');
    findUser(1).then((user) => {
    console.log('end, user= ' + userMapping(user));
    });
    
  • 실행결과
    1
    2
    3
    
    start
    waited 0.1 sec.
    end, user= id:1,name:User1,email:1@test.com
    

참고자료

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