본문 바로가기

IT

동기 / 비동기 & 블로킹 / 논블로킹 조합

1. 동기 + 블로킹 (가장 일반적)

// Java의 일반적인 파일 읽기
String content = Files.readString(Paths.get("file.txt")); 
System.out.println("파일 내용: " + content); 
System.out.println("다음 작업 수행");
  1. readString() 호출
  2. 파일 읽기 완료까지 대기 (블로킹)
  3. 호출자가 완료를 확인 (동기)
  4. 다음 코드 실행

특징: 함수가 완료될 때까지 기다리고(블로킹), 호출자가 완료 여부를 직접 확인함(동기)

 

2. 동기 + 논블로킹

// Java NIO의 논블로킹 소켓
SocketChannel channel = SocketChannel.open();
channel.configureBlocking(false);

while (true) { 
  int bytesRead = channel.read(buffer);
  
  if (bytesRead > 0) { // 데이터 처리
    break; 
  } else if (bytesRead == 0) { // 아직 데이터가 없음, 다른 작업 수행
    doOtherWork(); 
  } 
}
  1. channel.read() 호출
  2. 즉시 리턴 (논블로킹)
  3. 호출자가 반복적으로 상태 확인 (동기)
  4. 완료될 때까지 폴링 반복

특징: 함수가 즉시 리턴하지만(논블로킹), 호출자가 지속적으로 완료 여부를 확인해야 함(동기). CPU 자원 낭비 가능성이 있음.

 

3. 비동기 + 블로킹 (비효율적)

// 잘못 구현된 비동기 예시
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { 
  return readFileSlowly(); 
}); // 비동기로 시작했지만 즉시 get()으로 블로킹

String result = future.get(); // 여기서 블로킹 발생
System.out.println(result);
  1. 비동기 작업 시작
  2. 즉시 future.get() 호출로 블로킹
  3. 비동기 작업이 완료 통지 (비동기)
  4. 결과 획득

특징: 비동기 방식을 사용했지만 결과를 기다리면서 블로킹됨. 비동기의 장점을 살리지 못하는 안티패턴.

 

4. 비동기 + 논블로킹 (이상적)

// Node.js 스타일의 비동기 논블로킹
CompletableFuture.supplyAsync(() -> { 
  return readFileSlowly(); 
}).thenAccept(content -> { 
  System.out.println("파일 내용: " + content); 
}).thenRun(() -> { 
  System.out.println("후속 작업 수행"); 
}); 
System.out.println("즉시 실행되는 다른 작업");
  1. 비동기 작업 시작
  2. 즉시 리턴, 다른 작업 수행 (논블로킹)
  3. 작업 완료 시 콜백 자동 실행 (비동기)
  4. 최대 성능과 응답성 확보

특징: 함수가 즉시 리턴하고(논블로킹), 완료되면 시스템이 알아서 처리함(비동기)

 

🔍 핵심 정리

  • 동기/비동기: 작업 완료를 누가 신경쓰느냐의 문제
  • 블로킹/논블로킹: 제어권을 언제 반납하느냐의 문제

'IT' 카테고리의 다른 글

GitHub Actions CI/CD  (0) 2025.05.27
스레드의 이해  (1) 2025.02.24
프로세스 간 통신의 이해 : 소켓과 RPC  (1) 2025.02.23
프로세스 간 통신의 이해 : 공유 메모리와 파이프  (0) 2025.02.23
프로세스 간 통신(IPC)  (0) 2025.02.22