1. 동기 + 블로킹 (가장 일반적)
// Java의 일반적인 파일 읽기
String content = Files.readString(Paths.get("file.txt"));
System.out.println("파일 내용: " + content);
System.out.println("다음 작업 수행");
- readString() 호출
- 파일 읽기 완료까지 대기 (블로킹)
- 호출자가 완료를 확인 (동기)
- 다음 코드 실행
특징: 함수가 완료될 때까지 기다리고(블로킹), 호출자가 완료 여부를 직접 확인함(동기)
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();
}
}
- channel.read() 호출
- 즉시 리턴 (논블로킹)
- 호출자가 반복적으로 상태 확인 (동기)
- 완료될 때까지 폴링 반복
특징: 함수가 즉시 리턴하지만(논블로킹), 호출자가 지속적으로 완료 여부를 확인해야 함(동기). CPU 자원 낭비 가능성이 있음.
3. 비동기 + 블로킹 (비효율적)
// 잘못 구현된 비동기 예시
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
return readFileSlowly();
}); // 비동기로 시작했지만 즉시 get()으로 블로킹
String result = future.get(); // 여기서 블로킹 발생
System.out.println(result);
- 비동기 작업 시작
- 즉시 future.get() 호출로 블로킹
- 비동기 작업이 완료 통지 (비동기)
- 결과 획득
특징: 비동기 방식을 사용했지만 결과를 기다리면서 블로킹됨. 비동기의 장점을 살리지 못하는 안티패턴.
4. 비동기 + 논블로킹 (이상적)
// Node.js 스타일의 비동기 논블로킹
CompletableFuture.supplyAsync(() -> {
return readFileSlowly();
}).thenAccept(content -> {
System.out.println("파일 내용: " + content);
}).thenRun(() -> {
System.out.println("후속 작업 수행");
});
System.out.println("즉시 실행되는 다른 작업");
- 비동기 작업 시작
- 즉시 리턴, 다른 작업 수행 (논블로킹)
- 작업 완료 시 콜백 자동 실행 (비동기)
- 최대 성능과 응답성 확보
특징: 함수가 즉시 리턴하고(논블로킹), 완료되면 시스템이 알아서 처리함(비동기)
🔍 핵심 정리
- 동기/비동기: 작업 완료를 누가 신경쓰느냐의 문제
- 블로킹/논블로킹: 제어권을 언제 반납하느냐의 문제
'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 |