Group Study (2022-2023)/Computer Science

[Computer Science] 3주차 스터디 - 동시성과 병렬성, 동기 비동기

spring_sunshine 2023. 2. 13. 18:48

동시성과 병렬성

동시성

  • 동시성은 여러 작업이 겹치는 기간에 실행될 수 있음을 의미한다.
  • 동시에 실행하는 것이 아니라 CPU가 작업마다 시간을 분할하여 적절하게 context switching을 통해 동시에 실행되는 것처럼 보이게 하는 것이다.
  • 동시성의 핵심 목표는 유휴 시간을 최소화하는 것이다. (유휴 시간: 컴퓨터가 작동가능하나 작업이 없는 시간)
  • 구현과 디버그가 어렵다는 단점이 있다.
  • 현재 프로세스/스레드가 I/O 작업, DB 트랜잭션 등 외부 프로그램 실행을 기다리는 동안에 다른 프로세스/스레드가 CPU 할당을 받는다.

병렬성

  • 병렬성은 동일한 시간에 독립적인 작업을 실행할 수 있음을 의미한다.
  • 동시성과는 달리 여러 작업을 다른 코어, 다른 프로세스, 별도의 컴퓨터 등에서 동시에 실행할 수 있다.
  • 그래서 병렬 처리가 성능 향상에 필수적이라고도 한다.
  • 한가지 예로 분산 컴퓨팅 시스템이 있다. 분산 컴퓨팅 시스템은 단일 시스템으로 실행하는 여러 컴퓨터 시스템들로 구성되어 있고, 각 컴퓨터의 시스템들은 네트워크로 연결될 수 있다. 해당 예 외로도 하나의 컴퓨터에 여러 코어를 사용하여 병렬 처리를 활용할 수도 있다.

동시성 vs 병렬성

  • 프로그래밍 실습 강의를 들으면서 영상을 멈췄다가 다시 실행하는 행위를 반복 → 동시성
  • 코딩을 하면서 여유롭게 음악을 감상 → 병렬성

아래 그림처럼 2개의 코어가 있다고 가정했을 때, 동시성의 경우는 Core1에서만 Task를 실행하고 있고 시간이 흐름에 따라 Task1과 2를 번갈아가며 실행한다.

병렬성의 경우에는 Task1과 2를 번갈아가며 실행할 필요없이 각 코어에서 Task를 독립적으로 실행한다.

동시성은 여러 Task를 계속 번갈아가며 실행하기 때문에 만약 Task1과 2가 같은 자원을 접근한다면 자원의 값이 변경되면서 서로의 실행 결과에 영향을 미칠 수도 있고, 또 어떤 기준으로 Task를 선택하고 교환해야 할 것인지도 고려해야 한다. Race Condition, Deadlock, Starvation 등의 문제가 생길 수 있다.

  • Race Condition: 여러 프로세스가 하나의 자원에 접근해 서로의 실행 결과에 영향을 주는 현상
  • Deadlock: 여러 프로세스가 서로 상대방의 작업이 끝나기를 무한히 기다리는 현상
  • Starvation: 특정 프로세스가 우선순위가 낮아 원하는 자원을 계속 할당 받지 못하는 현상

즉, 동시성은 작업이 빠르게 번갈아가며 실행되기에 동시에 실행되는 것 같이 보이는 것이고, 병렬성은 실제로 동시에 작업을 처리하는 것을 의미한다.


동기와 비동기

  • 주로 어플리케이션에서 자주 다뤄지는 개념이며, 다음 작업이 요청되는 시간과 관련되어 있다.
  • 처리해야 할 작업들을 **어떠한 '흐름'**으로 처리 할 것인가에 대한 관점

<비유를 통한 쉬운 설명>

  • 해야할 일(task)가 빨래, 설거지, 청소 세 가지가 있다고 가정한다. 이 일들을 동기적으로 처리한다면 빨래를 하고 설거지를 하고 청소를 한다. 비동기적으로 일을 처리한다면 빨래하는 업체에게 빨래를 시킨다. 설거지 대행 업체에 설거지를 시킨다. 청소 대행 업체에 청소를 시킨다. 셋 중 어떤 것이 먼저 완료될지는 알 수 없다. 일을 모두 마친 업체는 나에게 알려주기로 했으니 나는 다른 작업을 할 수 있다. 이 때는 백그라운드 스레드에서 해당 작업을 처리하는 경우의 비동기를 의미한다.

동기

  • 현재 작업의 응답이 끝남과 동시에 다음 작업이 요청된다.
  • 함수를 호출하는 곳에서 호출되는 함수가 결과를 반환할 때까지 기다린다.
  • 함수 A가 함수 B를 호출한 뒤, 함수 B의 리턴값을 계속 신경쓰면서 확인한다.
function run(a,b) {
	return a+b
}
const result = run(1,2);

console.log("시작");
console.log("결과:",result)
console.log("끝");

/*
출력결과:
시작
결과:3
끝
*/

비동기

  • 현재 작업의 응답이 끝나지 않은 상태에서 다음 작업이 요청된다.
  • 함수를 호출하는 곳에서 결과를 기다리지 않고, 다른 함수(callback)에서 결과를 처리한다.
  • 함수 A가 함수 B를 호출할 때 콜백함수를 함께 전달해서, 함수 B의 작업이 완료되면 함께 보낸 콜백 함수를 실행한다.
  • 함수 A는 함수 B를 호출한 후 함수 B의 작업 완료 여부에는 신경쓰지 않는다.
function run(a,b) {
	return a+b
}
let result;
setTimeout(()=> {
	result = run(1,2);
},1000);

console.log("시작");
console.log("결과:",result);
console.log("끝");

/*
출력결과:
시작
결과:undefined
끝
*/

블로킹과 논블로킹

  • 주로 멀티스레딩, I/O 등에서 사용되는 개념이며, 함수의 리턴 시점과 제어권에 따라 차이가 난다.
  • 처리되어야 하는 (하나의) 작업이, 전체적인 작업의 '흐름'을 막느냐 안막느냐 에 대한 관점
  • 즉, 제어권이 누구한테 있느냐가 관심사

블로킹

  • 제어권이 호출된 함수에게 넘어가서 호출된 함수 내의 작업이 모두 끝난 후에 호출한 함수에게 다시 제어권이 넘어온다.
  • 작업이 완료된 후 새로운 작업을 수행할 수 있다.
function run() {
//오래 걸리는 작업
    console.log("작업끝");
}

console.log("시작");
run();
console.log("다음작업");

/*
출력 결과:
시작 
작업끝 
다음작업
*/

논블로킹

  • 제어권이 계속 호출한 함수에게 있기 때문에 작업의 완료여부와 관계없이 새로운 작업을 수행할 수 있다.
function run() {
//오래 걸리는 작업
    console.log("작업끝");
}

console.log("시작");
setTimeout(run,0);
console.log("다음작업");

/*
출력결과:
시작
다음작업
작업끝
*/

이렇게만 보면 동기-블로킹, 비동기-논블로킹을 완전히 동일한 개념으로 생각할 수 있으나, 주요 관심사가 무엇인지에 따라 차이가 난다.

여기서 상위 프로세스인 선생님(teacher)이 있고, 하위 프로세스인 학생들(student)이 있다고 가정해보자. 각각의 선생님은 학생들에게 자습을 시키는데, 이때 선생님들마다 각자의 자습 스타일이 있다.

동기+블로킹

  • 나이가 지극하신 FM 선생님
  • 입실 후 학생들의 자습이 모두 끝날 때까지 아무것도 하지 않으면서 기다리고, 학생들이 자습이 끝나면 퇴실한다.
function students(){
	for(i=1;i<11;i++){
    	console.log('학생들: ${i}번 문제 푸는중');
    }
}

function teacher(){
	console.log("선생님 입실");
    student();
    console.log("선생님 퇴실");
}
teacher();

/*
출력결과:
선생님 입실
학생들: 1번 문제 푸는중
...
학생들: 10번 문제 푸는중
선생님 퇴실
*/
  • 가장 많이 쓰이는 조합 중 하나이다.
  • 모든 실행과 흐름이 순차적이기 때문에 개발자가 프로그램을 제어하기 쉽다.
  • 상위 프로세스는 하위 프로세스의 작업 완료 여부를 신경쓴다.
  • 블로킹이므로 하위 프로세스의 작업이 완료되지 않으면 상위 프로세스는 다른 작업을 할 수 없다.

비동기+논블로킹

  • 아주 바빠서 자신의 시간이 소중한 선생님
  • 입실 하자마자 자습을 시킨 후 바로 퇴실한다. 학생들의 자습이 끝나면 반장을 통해 보고받는다.
function students(callback){
	let i=1;
    const interval = setInterval(()=>{
    	if(i>0){
        	callback();
            clearInterval(interval);
        }
        else{
        	console.log('학생들: ${i}번 문제 푸는중');
            i++;
        }
    },10);
}

function teacher(){
	console.log("선생님 입실");
    students(()=>console.log("반장: 마무리 후 보고"));
    console.log("선생님 퇴실");
}
teacher();

/*
출력결과:
선생님 입실
선생님 퇴실
학생들: 1번 문제 푸는중
...
학생들: 10번 문제 푸는중
반장: 마무리 후 보고
*/
  • 가장 많이 쓰이는 조합 중 하나이다.
  • 성능과 자원의 효율면에서 가장 우수하다.
  • 상위 프로세스는 하위 프로세스의 작업 완료 여부를 신경쓰지 않는다.
  • 논블로킹이므로 하위 프로세스의 작업 완료 여부와 상관없이 상위 프로세스는 다른 작업을 할 수 있다.

동기와 비동기, 블로킹과 넌블로킹의 차이는 무엇인가요?

  • 동기/비동기는 인터럽트 발생으로 인한 제어권 반환 시점에 중점을 두고, Blocking/Non-bloking은 제어권 자체에 중점을 둔다는 점에서 차이가 있다.
  • 동기와 비동기는 프로세스의 수행 순서 보장에 대한 매커니즘이고 블록킹과 논블록킹은 프로세스의 유휴 상태에 대한 개념으로 완전한 별개의 개념이라는 것이다.

자바스크립트에서 비동기 구현하는 방법

  • 자바스크립트에서 async, await 키워드나 콜백 함수로 비동기 처리를 할 수 있다. async 키워드와 함께 선언한 함수 내부에서는 await 문법을 사용할 수 있는데, async 함수의 실행 후 반환 값은 Promise이다.

동시성과 병렬성의 차이?

  • 설계적으로 차이가 있다. 동시성은 소프트웨어적 설계에 가깝고, 병렬성은 하드웨어적 설계에 가깝다.