[운영체제] 동기 / 비동기, 블로킹 / 논블로킹

kimgwon·2023년 9월 4일

CS

목록 보기
4/10
post-thumbnail

Ⅰ. 동기/비동기, 블로킹/논블로킹

  • 동기/비동기
    • 행위에 대한 이야기이다.
    • 요청한 작업에 대해 완료 여부를 신경 써서 작업을 순차적으로 수행할지 아닌지에 대한 관점이다.
  • 블로킹/논블로킹
    • 함수 호출에서의 이야기이다.
    • 요청한 작업이 다 끝난 후 응답을 보내는지 아닌지에 대한 관점이다.

1. 동기/비동기

  • 동기(Synchronous)
    • 요청한 작업에 대해 완료 여부를 따져 순차대로 처리하는 것이다. 즉, 요청에 대한 응답의 순서가 보장된다.
    • A, B, C 작업을 요청했을때 응답의 결과로 A->B->C 순서가 보장된다.
  • 비동기(Asynchronous)
    • 요청한 작업에 대해 완료 여부를 따지지 않고 다른 작업들 또한 동시에 처리되는 것이다. 즉, 요청에 대한 응답의 순서가 보장되지 않는다.
    • I/O 작업과 같이 느린 작업이 발생할 때 기다리지 않고 다른 작업을 같이 처리하므로 동시에 처리하는 멀티 작업을 진행할 수 있다. 이는 전반적인 시스템 성능 향상에 도움을 줄 수 있다.
    • A, B, C 작업을 요청했을때 응답의 결과로 A, B, C 순서가 보장되지 않는다.


2. 블로킹/논블로킹

  • 블로킹
    • 호출한 함수가 호출된 함수에 제어권을 넘기는 것이다.
    • A 함수가 B 함수를 호출한다면, A 함수는 B 함수를 호출하면서 제어권을 넘기고 A는 제어권이 없으므로 함수 실행을 멈춘다. B 함수는 작업이 모두 끝난 후 결과를 리턴한다.
  • 논블로킹
    • 호출한 함수가 호출된 함수에 제어권을 넘기지 않는 것이다.
    • A 함수가 B 함수를 호출한다면, A 함수는 B 함수를 호출만 하고 제어권은 넘기지 않는다. A는 제어권을 그대로 갖고 있으므로, 함수를 계속 실행한다. B 함수는 행위를 끝마쳤는지에 대한 유무를 바로 리턴한다.

제어권
함수의 코드나 프로세스의 실행 흐름을 제어할 수 있는 권리를 말한다.


Ⅱ. 동기/비동기 + 블로킹/논블로킹 조합

1. Sync Blocking (동기 + 블로킹)

호출한 작업이 진행되는 동안 자신의 작업을 멈추고 호출한 작업이 끝난 후 그 결과를 받으며(Blocking), 호출한 작업의 완료 여부를 받은 후 순차적으로 자신의 작업을 처리(Sync)하는 방식이다.

  • 실생활 예시

    1. 사장🥸: (알바생a에게 커피a를 부탁한다.)
    2. 알바생a: 네. (커피a 제작 중)
    3. 사장🥸: (알바생a이 작업을 다 할 때 까지 아무 일도 하지 않고 기다린다.) -> 블로킹
    4. 알바생a: (커피a을 제작 완료) 커피1 제작 완료 했습니다.
    5. 사장🥸: (알바생b에게 커피b를 부탁한다.) -> 동기 (순차적이다.)
    6. 알바생b: 네. (커피b 제작 중)
    7. 사장🥸: (알바생b가 작업을 다 할 때 까지 아무 일도 하지 않고 기다린다.) -> 블로킹
    8. 알바생b: (커피b를 제작 완료) 커피b 제작 완료 했습니다.
    9. 사장🥸: (알바생c에게 커피c을 부탁한다.) -> 동기 (순차적이다.)
      ...
  • 코드 동작 예시

    const fs = require('fs'); // 파일 시스템 모듈 불러오기
    
    // 동기적으로 파일 읽기
    const data1 = fs.readFileSync('file1.txt', 'utf8'); // file1을 sync으로 read 함
    console.log(data1); // 파일 내용 출력하고 적절한 처리를 진행
    
    const data2 = fs.readFileSync('file2.txt', 'utf8'); 
    console.log(data2); 
    
    const data3 = fs.readFileSync('file3.txt', 'utf8'); 
    console.log(data3);

2. Sync Non-Blocking (동기 + 논블로킹)

호출한 작업이 진행되는 동안에도 자신의 작업을 처리하고 호출한 작업의 결과 처리 유무를 바로 받으며(Non-Blocking), 호출한 작업의 완료 여부를 받은 후 순차적으로 자신의 작업을 처리(Sync)하는 방식이다.

  • 실생활 예시

    1. 사장🥸: (알바생a에게 커피a를 부탁한다.)
    2. 알바생a: 네. (커피a 제작 중)
    3. 사장🥸: 커피a 다 만들었나요? -> 동기, 논블로킹 (알바생a를 끊임없이 확인하며, 알바생a의 작업 결과를 기다린다.)
    4. 알바생a: (커피a 제작 중) 만드는 중 입니다. -> 논블로킹 (처리 유무를 바로 리턴한다.)
    5. 사장🥸: 커피a 다 만들었나요?
    6. 알바생a: (커피a 제작 중) 만드는 중 입니다.
    7. 알바생a: (커피a 제작 완료) 커피a 제작 완료 했습니다.
    8. 사장🥸: (알바생b에게 커피b를 부탁한다.) -> 동기 (다른 일을 하지 않고, 알바생a의 작업이 끝난 후 자신의 일을 처리한다. 즉, 순차적이다.)
    9. 알바생b: 네. (커피b 제작 중)
    10. 사장🥸: 커피b 다 만들었나요?
    11. 알바생b: (커피b 제작 중) 만드는 중 입니다.
    12. 사장🥸: 커피b 다 만들었나요?
      ...
  • 코드 동작 예시
    동기 + 논블로킹 코드를 표현하는데 적합한 대중적인 언어로 자바를 들 수 있다. 스레드 객체를 만들어 요청 작업을 백그라운드에 돌게 하고, 메인 메서드에서 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");
        }
    }

3. Async Blocking (비동기 + 블로킹)

호출한 작업이 진행되는 동안 자신의 작업을 멈추고 호출한 작업이 끝난 후 그 결과를 받으며(Blocking), 순차적으로 작업이 수행됨을 보장하지 않는(Async) 방식이다. 실무에서 잘 마주하지 않아 다룰 일이 거의 없다.
Sync-blocking과 개념적으로 차이가 있지만, 성능적으로 차이가 없다. 보통 Asnyc-blocking은 개발자가 Async-NonBlocking으로 처리하려다가 실수하는 경우에 발생한다. 그래서 이 방식을 안티 패턴이라고 치부하기도 한다.

  • 실생활 예시
    중간에 블로킹 되는 지점이 있지만, 비동기로 동작한다.
    1. 사장🥸: (알바생a에게 커피a를 부탁한다.)
    2. 알바생a: 네. (커피a 제작 중)
    3. 사장🥸: (알바생b에게 커피b를 부탁한다.) -> 비동기
    4. 사장🥸: (알바생b가 작업을 다 할 때 까지 기다린다.) -> 블로킹
    5. 알바생b: (커피b 제작 완료) 커피b 제작 완료 했습니다.
    6. 사장🥸: (알바생c에게 커피c를 부탁한다.) -> 비동기
    7. 알바생a: (커피a 제작 완료) 커피a 제작 완료 했습니다. -> 비동기 (순차적으로 작업이 수행됨을 보장하지 않는다.)
    8. 알바생c: 네. (커피c 제작 중)
    9. 사장🥸: (다른 작업을 한다.) -> 비동기
      ...

4. Async Non-Blocking (비동기 + 논블로킹)

호출한 작업이 진행되는 동안에도 자신의 작업을 처리하고 호출한 작업의 결과 처리 유무를 바로 받으며(Non-Blocking), 순차적으로 작업이 수행됨을 보장하지 않는(Async) 방식이다.

  • 실생활 동작 예시

    1. 사장🥸: (알바생a에게 커피a를 부탁한다.)
    2. 알바생a: (커피a 제작 중) 만드는 중 입니다. -> 논블로킹 (처리 유무를 바로 리턴한다.)
    3. 사장🥸: (알바생b에게 커피b를 부탁한다.) -> 비동기
    4. 알바생b: (커피b 제작 중) 만드는 중 입니다. -> 논블로킹 (처리 유무를 바로 리턴한다.)
    5. 사장🥸: (알바생c에게 커피c를 부탁한다.)
    6. 알바생c: (커피c 제작 중) 만드는 중 입니다. -> 논블로킹 (처리 유무를 바로 리턴한다.)
    7. 사장🥸: (다른 작업을 한다.)
    8. 알바생b: (커피b 제작 완료) 커피b 제작 완료 했습니다. -> 비동기 (요청 순서와 처리 순서가 다르다.)
    9. 알바생a: (커피a 제작 완료) 커피a 제작 완료 했습니다.
    10. 알바생c: (커피c 제작 완료) 커피c 제작 완료 했습니다.
      ...
  • 코드 동작 예시
    Sync Blocking에서 구현한 코드를 Asnyc Non-Blocking 방식으로 구현한 것이다. 차이점은 호출 함수에 콜백 함수를 넣음으로써 작업의 결과를 후처리 할 수 있다.

    // 비동기적으로 파일 읽기
    const fs = require('fs'); // 파일 시스템 모듈 불러오기
    
    fs.readFile('file.txt', 'utf8', (err, data) => { // 파일 읽기 요청과 콜백 함수 전달
      if (err) throw err; // 에러 처리
      console.log(data); // 파일 내용 출력
    });
    
    fs.readFile('file2.txt', 'utf8', (err, data) => {
      if (err) throw err; 
      console.log(data);
    });
    
    fs.readFile('file3.txt', 'utf8', (err, data) => { 
      if (err) throw err; 
      console.log(data);
    });
    
    console.log('done'); // 작업 완료 메시지 출력

참고

https://inpa.tistory.com/entry/%F0%9F%91%A9%E2%80%8D%F0%9F%92%BB-%EB%8F%99%EA%B8%B0%EB%B9%84%EB%8F%99%EA%B8%B0-%EB%B8%94%EB%A1%9C%ED%82%B9%EB%85%BC%EB%B8%94%EB%A1%9C%ED%82%B9-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC
https://hamait.tistory.com/m/930

0개의 댓글