새소식

🙋‍♂️ Welcome to xuvlog :)

🧑‍💻 Backend

동기 / 비동기와 블로킹 / 논블로킹 개념

  • -

동기 VS 비동기 / 블로킹 VS 논 블로킹

둘은 서로 다른 관점의 개념이다 → 헷갈릴 때는 “어떤 관점에서 생각하고 있는지”에 대해 생각해보자.
 
동기 / 비동기는 코드가 어떤 순서로 흘러가냐의 관점
블로킹 / 논블로키은 컴퓨터 자원 수준에서 작업을 기다리는가에 대한 관점
 

동기 VS 비동기

동기 방식

동기 (Synchronous) 방식은 우리가 일상적으로 경험하는 가장 직관적인 처리 방식.
동기 방식은 현재 작업이 끝나기 전에 절대 다음 작업으로 넘어가지 않는다.
 
public class Basic {

    @Test
    public void makeBreadSynchronously() {
        System.out.println("1. 반죽하기");
        System.out.println("2. 오븐에 빵 굽기");
        try {
            Thread.sleep(1000); // 오븐에 굽는 시간
        } catch (InterruptedException e) {
        }
        System.out.println("!!! 빵 굽기 완료!!!");

        System.out.println("=== 빵 먹기 전 ===");
        System.out.println("3. 빵 먹기");
    }
}
 
현재 코드는 순차적으로 한줄 씩 실행 된다.
→ 즉 동기 방식의 핵심은 이전 단계가 완벽하게 완료되길 기다린 후에 실행 되는 방식
 

비동기 방식

비동기 방식 (Synchronous) 은 작업이 끝나길 기다리지 않고 다음 코드를 즉시 실행.
즉, 작업이 끝나기를 기다리는 동안 다음 코드 실행 가능
 
public class Basic {
    @Test
    public void makeBreadAsynchronously() {
        System.out.println("1. 반죽하기");
        System.out.println("2. 오븐에 빵 굽기");
        CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
                    try {
                        Thread.sleep(1000); // 오븐에 굽는 작업
                    } catch (InterruptedException e) {
                    }
                })
                // "빵 굽기" 가 완료되면 할 일을 정의합니다.
                .thenRun(() -> System.out.println("!!! 빵 굽기 완료!!!"));

        System.out.println("=== 빵 먹기 전 ===");
        completableFuture.join();
        System.out.println("3. 빵 먹기");
    }
}

 
Java의 CompletableFuture 클래스를 통해 미래의 작업을 정의 하고 실행 → 구체적 흐름은 다음과 같다.
  1. 반죽하기 출력 (동기)
  2. 오븐에 빵 굽기 출력 (동기)
  3. 비동기 방식으로 오븐에 빵 굽는 작업 진행 (Thread.sleep이 여기선 빵 굽는 작업이라고 가정) → 이후 빵 굽고 할일 정의
  4. 빵 굽는 작업이 끝나는 것 과 무관하게 “빵 먹기 전” 동기적 실행
  5. join() 시점에는 빵굽는 작업이 끝나기까지 대기 해야한다
  6. 이후 빵 굽는 작업 완료 → 빵 굽기 완료 출력
  7. 빵 굽기가 완료 되면 빵 먹기 출력
 
중요한 포인트는 코드가 순차적으로 실행되지 않는다는 점이다.
 
정리하면 동기/비동기 방식은 우리가 작성한 코드가 어떤 방식으로 흘러가느냐에 대한 관점으로 봐야 한다.
 
 

블로킹 VS 논 블로킹

“컴퓨터 자원 수준에서 작업을 기다리는가 ?“ -> 실제로 스레드가 동작하는 로직을 생각해보자
 

블로킹

블로킹 방식은 특정 작업을 시작하면, 그 작업이 끝날 때 까지 쓰레드가 멈춰서 대기.
즉 쓰레드는 작업 결과를 기다리느라 작업이 끝날 때까지 실제로 멈춘다.
 
@Test
public void makeBreadSynchronously() {
    System.out.println("1. 반죽하기");
    System.out.println("2. 오븐에 빵 굽기");

    try {
	// 이 부분에서 스레드가 정말 '잠들어서' 대기 (Thread.sleep)
        Thread.sleep(1000); // 오븐에 굽는 시간
    } catch (InterruptedException e) {
    }
    
    // 여기까지 오븐에서 빵 굽기가 끝날 때까지 '블로킹' 상태로 기다림
    System.out.println("!!! 빵 굽기 완료!!!");

    System.out.println("=== 빵 먹기 전 ===");
    System.out.println("3. 빵 먹기");
}
 
동기에서 본 코드와 100% 같은 코드를 블로킹 / 논 블로킹 관점으로 보자.
Thread.sleep() 에서는 쓰레드가 반드시 1초동안 멈춰 있어야 한다.
“빵 굽기 완료” 코드가 수행되기 전까지 반드시 멈춰있어야 한다.
 

논블로킹

작업을 시작하고, 해당 작업을 스레드가 멈춰서 기다리지 않고 곧바로 반환되어 다른 작업 수행 가능 → 작업 결과를 기다리면서도 스레드가 다른 작업 가능
@Test
public void makeBreadAsynchronously() {
    // 현재 스레드가 출력합니다. - main-thread-01
    System.out.println("1. 반죽하기");
    System.out.println("2. 오븐에 빵 굽기");
    
    // '오븐에 빵 굽기' 작업을 별도 스레드로 시작 -  async-thread-02
    CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
            })
            // "빵 굽기" 가 완료되면 할 일을 정의합니다.
            .thenRun(() -> System.out.println("!!! 빵 굽기 완료!!!"));

    // 현재 스레드가 빵 굽기를 기다리지 않고, 아래의 코드를 출력합니다.
    // main-thread-01가 안 기다리고 바로 일함. -> Non Blocking 
    System.out.println("=== 빵 먹기 전 ===");

    // 현재 스레드가 빵이 구워지기를 기다립니다. '오븐에 빵 굽기' 완료가되어야만 넘어갈 수 있음
    // main-thread-01 이 기다려야 하는 상황. 기다려야 해!!!! -> 메인스레드가 막힘
    // -> Blocking
    completableFuture.join();

    // main-thread-01 수행
    System.out.println("3. 빵 먹기");
}
여기서도 스레드가 대기 하냐 ? 안하냐 ? 의 관점으로 보자.
  1.  반죽하기, 오븐에 빵 굽기는 메인스레드가 처리한다
  2. 오븐에 빵굽기 작업은 async 스레드가 따로 처리
  3. 메인 스레드는 바로 빵먹기전 코드 수행 → 논블로킹이기 때문에 바로 수행
  4. 이후 join()에서는 빵이 구워지기를 기다려야 한다.
  5. 이후 빵이 구워지면 메인 스레드가 빵 먹기 출력
 
정리하면, 다음과 같이 “관점”에 따라 두가지 개념을 떠올리면 될 것 같다.
  • 동기 VS 비동기 : 코드의 흐름의 연결성에 대해 따져보자
  • 블로킹 VS 논 블로킹 : 자원(대표적으로 스레드)이 묶이느냐 아니냐
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.