반응형

Blocking과 Non-Blocking, Sync와 Async 그만 헷갈리기

 

OS를 공부하면서 Blocking과 Non-Blocking, Sync와 Async 개념을 이해했었는데, 다시 떠올려보니 너무 헷갈렸다.
특히 둘을 섞어서 생각해보면 더 혼란스러워졌다. 
헷갈리는 것을 찾아보다가, 우연히 보게 된 좋은 예시가 있어서 정리해두고자 한다.


사무실에 있다. 복합기를 사용해서 스캔을 뜨고싶다. 그런데 문서의 양이 많아서 시간이 좀 오래걸린다.
10분 이상 걸린다고 가정하자.

복합기의 시작 버튼을 눌렀다. 그리고 그 앞에서 스캔이 완료될 때까지 하염없이 기다렸다가 스캔 된 파일 결과물을 갖게 된다면, 이것은 Blocking 이다. 10분은 아무것도 안하기에는 꽤 긴시가이다. Blocking 방식에는 다른 일을 모두 중지하고 해당 작업이 완료되기만을 오매불망 기다리는 기다림이 항상 포함된다.

반면, Non-Blocking은 기다림이 없다. 시작 버튼을 눌러 놓고 뭔가 다른 일을 한다. 다시 힐끗 확인 했을 때, 아직 스캔중이라면, 잠시 잊어버리고 다시 다른 일에 집중한다. 조금 있다가 또 힐끗 확인했을 때, 완료되었다면, 이제 결과물을 가질 수 있다. 이것에 Non-Blocking이다.

그리고 이 행위들을 내가 직접 한다면 synchronous(*Sync) 이다.
반면에 내가 직접 하지 않고 누군가를 시킨다면 asynchronous(*Async)이다.

정리하자면 아래와 같다.

  • 기다림 Blocking / 기다리지 않음 Non-Blocking
  • 내가 함 Synchronous / 다른 사람 시킴 Asynchronous

종종 non-blocking과 Async 를 헷갈리는 이유는 어쨋거나 "내가 기다림으로부터 자유롭다" 라는 공통점 때문인 것 같다.

 

두가지 서로 다른 개념을 섞어서 생각해보자.

  • Sync-Blocking
    • 앞의 Blocking 설명과 사실상 동일하다. 내가 복합기 앞으로 간다. 스캔 시작 버튼을 누른다. 다른 일 못하고 기다린다. 완료되면 그제야 내자리로 돌아가 스캔 완료된 파일을 사용한다.
  • Sync-NonBlocking
    • 앞의 Non-Blocking 설명과 동일하다. 내가 복합기 시작 버튼을 누른다. 자리로 돌아온다. 틈틈히 스캔이 완료되었는지 확인해줘야 한다. 하지만 다른 일을 할 수 있다. 다른일을 못 하면서까지 앞에 가서 기다리지는 않는다.
  • Async-Blcoking
    • 드디어 심부름꾼이 등장한다. 나는 내 자리에 그대로 앉아있는다. 나는 다른 일을 하는 동안, 심부름꾼에게 스캔을 하도록 시킨다. 심부름 꾼이 복합기 앞으로 간다. 스캔 시작 버튼을 누른다. 이 사람은 다른 일 못하고 이것만 기다린다. 완료되면 심부름꾼은 내 자리로 돌아와 스캔이 완료되었다고 알려준다.
  • Async-NonBlocking
    • 나는 내 자리에 앉아서 일하는 동안, 심부름꾼에게 스캔을 하도록 시킨다. 심부름꾼이 복합기 앞으로 가서 시작 버튼을 누른다. 심부름군은 스캔을 기다리면서 커피를 내려 마시면서 일기를 쓴다. 일기를 쓰는 동안, 틈틈이 스캔이 완료되었는지 곁눈질로 확인한다. 스캔이 완료되면 내 자리로 돌아와 스캔이 완료되었다고 알려준다.

 

케이스 분류의 의미

그러면 위의 네가지 케이스 중에서, 두 사람의 '시간' 이라는 자원을 가자 효율적으로 사용한 경우는 무엇일까?

아래의 그림을 보면 명확하다. 
아무것도 하지 않고 기다리는 시간(또는 중간에 스캔이 완료되었는지 체크하는 시간)을 빈칸으로, 다른 작업 중인 시간을 색칠된 칸으로 나타냈다. 한마디로, 색칠된 면적이 클수록 시간을 효율적으로 사용했다고 볼 수 있다. 단순화 시키기는 했지만말이다.

Async-NonBlocking이 가장 효율적이고, Sync-Blocking이 가장 비효율적이라고 볼 수 있습니다.

여기서 '시간' 비유를 통해 나타내고 싶었던 주인공은 사실, 'CPU'이다.
컴퓨터에서 아무것도 하지 않고 있는 시간은 곧 CPU의 낭비라고 볼 수 있으니까 말이다. 
촘촘하게 시간을 사용한다는 것은 곧 CPU 라는 컴퓨팅 자원을 효율적으로 사용한다는 뜻이다.
그렇다면, Async-Non-Blocking 방식을 사용할 때 가장 효율적이라는 결론이 나온다.

 

운영체제 입장에서

이제 비유를 빼고, 운영체제의 입장에서 개발의 언어로 다시 말해보겠다.

I/O 요청은 파일 읽기와 같은 디스크 I/O 요청, 소켓으로부터 읽기와 같은 네트워크 I/O 요청 등이 있다. CPU의 입장에서는 매우 시간이 오래 걸리는 작업이다.

I/O 요청을 Blocking으로 처리한다는 것은, 프로세스가 I/O를 위한 시스템 콜을 한 뒤 sleeping 이나 waiting 상태로 들어간다는 의미이다.
그동안 프로세스는 CPU를 놓아주고 아무것도 하지 않는 상태가 된다. I/O 처리가 완료되고 요청한 데이터가 준비되면, 그때 인터럽트가 발생해 프로세스가 재개된다.

반면 Non-Blocking I/O는 CPU를 놓지 않는다. Non-Blocking 옵션으로 시스템 콜을 호출하게 되면, 아직 I/O가 완료되지 않았다면 falsy한 값을 반환 받는다. 시간이 걸리는 I/O 요청을 처리하는 동안 이 CPU 자원을 이용해서 다른 작업을 하고 있을 수 있다.

Sync는 메인 흐름에서 순차적으로 처음부터 끝까지 처리한다.
반면 별도의 스레드를 만들어서 처리하거나, 이벤트 핸들러, 콜백 함수 등을 사용하는 경우를 async 라고 할 수 있다.

정리하자면 이렇다.

  • CPU를 놓음 Blocking / CPU를 놓지 않음 Non-Blocking
  • 같은 흐름에서 처리 Synchronous / 다른 흐름에서 처리 Asynchronous

 

반응형

'Operating System' 카테고리의 다른 글

연속 할당과 불연속 할당 / 쉽게배우는 운영체제를 완독하며...  (0) 2022.07.05
디렉터리의 구조  (0) 2022.07.04
파일과 파일 시스템  (0) 2022.07.03
RAID  (0) 2022.06.15
디스크 스케줄링  (0) 2022.06.14