동기/비동기
작업의 처리 순서와 흐름을 결정하는 중요한 개념으로, 멀티 스레드 환경이나 네트워크 통신에서 두 방식의 차이는 시스템의 성능과 안정성에 큰 영향을 미친다.
동기화
동기화(Synchronization)는 작업 요청과 결과가 순서대로 일치하여 처리되는 방식이다. 현재 진행 중인 작업이 완료될 때까지 다음 작업은 반드시 대기한다.
| 특징 | 설명 |
|---|---|
| 처리 방식 | 순차적 진행, Blocking 방식 |
| 작업 흐름 | 다음에 실행될 명령은 현재 실행 중인 명령 종료 시까지 대기한다. |
| 자원 접근 | 한 자원에 동시에 접근하는 것을 제한하여, 하나의 스레드가 독점적으로 자원을 사용하도록 보장한다. |
| 주요 목적 | 데이터의 일관성 및 무결성 유지, 시간적 동기화가 필요한 곳에 사용된다. |
| 문제점 | 대기 시간이 발생하여 전체 시스템의 처리 효율이 떨어질 수 있다. |
자바에서 멀티 스레드 환경에서 임계 영역의 동기화를 보장하기 위해 synchronized 키워드를 사용한다. 특정 코드 블록이나 메소드에 잠금(Lock)을 걸어 오직 하나의 스레드만이 해당 영역에 접근하도록 제한한다.
-
메소드 단위: 메소드 선언부에
synchronized키워드를 붙이면 메소드 전체가 잠금된다. -
블록 단위: 특정 코드 블록을 잠글 수 있다.
잠금이 걸리는 임계 영역은 작을 수록 다른 스레드의 대기 시간을 줄여 성능 저하를 최소화할 수 있어 블록 단위 활용이 일반적으로 더 효율적이다.
class User {
private int userNo = 0;
// synchronized 키워드 적용: 이 메소드 전체에 잠금을 건다.
public synchronized void add(String name) {
System.out.println(name + " : " + ++userNo);
}
}
// 결과: A: 0번째 사용 -> B: 1번째 사용 -> ... 순서대로 userNo 변수의 값 증가가 보장된다.
비동기화
비동기화(Asynchronization)는 작업 요청 후 결과가 돌아오기를 기다리지 않고 다음 작업을 즉시 실행하는 방식이다.
| 특징 | 설명 |
|---|---|
| 처리 방식 | 병렬적 진행, Non-Blocking 방식 |
| 작업 흐름 | 현재 실행 중인 명령이 종료되지 않아도 다음 명령을 실행한다. |
| 자원 접근 | (기본적으로는 접근 제한이 없으나)동시에 여러 스레드가 자원에 접근할 수 있다. |
| 주요 목적 | 전체 시스템의 효율과 응답성 향상 |
| 결과 확인 | 작업이 완료되면 Callback 메소드나 Future, Promise 등을 통해 결과를 나중에 통보받는다. |
비동기 방식은 속도가 빠르지만, 여러 스레드가 공유 자원에 동시에 접근하여 데이터를 변경할 경우 경쟁 상태(Race Condition)가 발생하여 데이터의 일관성 및 무결성이 깨질 수 있다.
class User {
private int userNo = 0;
// synchronized 키워드 미적용(비동기 접근 허용)
public void add(String name) {
// 임계 구역: userNo 변수를 읽고 1 증가시킨 후, 출력하는 3단계가 분리되며, 이 사이에 다른 스레드가 userNo 변수를 변경할 수 있다.
System.out.println(name + " : " + ++userNo);
}
}
/* 결과 예시:
A : 0번째 사용
B : 1번째 사용
C : 2번째 사용
A : 3번째 사용
C : 5번째 사용 <- B가 4를 출력해야 할 시점에 C가 5를 출력하는 등 순서가 꼬일 수 있다.
B : 4번째 사용
*/
동기화/비동기화의 선택 기준
두 방식은 트레이드 오프(Trade-Off) 관계에 있다. 따라서 시스템 설계 목표에 따라 적절한 방식을 선택해야 한다.
| 목표 | 선택 방식 | 예시 |
|---|---|---|
| 데이터 무결성 및 일관석 확보 | 동기화(Synchronization) | 금용 거래, DB 트랜잭션, 공유 자원 접근 |
| 시스템 응답성 및 처리 효율 향상 | 비동기화(Asynchronization) | 웹 요청(I/O), 대규모 병렬 처리, 사용자 인터페이스(UI) |
비동기 방식을 사용하되, 공유 자원에 접근하는 일부분(임계 영역)에만 synchronized 키워드나 Lock 객체를 사용하여 부분적인 동기화를 적용하는 것이 일반적이고 효율적인 방식이다.