병렬성
여러 작업을 여러 코어가 진짜 동시에 실행하는 것입니다.
동시성 vs 병렬성 비교
동시성 (Concurrency) - 1코어
→ 빠르게 번갈아 실행해서 동시처럼 보임
시간 →
Core1: [A][B][A][B][A][B]
병렬성 (Parallelism) - 멀티코어
→ 진짜 동시에 실행
시간 →
Core1: [A][A][A]
Core2: [B][B][B]
Java에서의 병렬 처리
Fork/Join Framework
// 큰 작업을 작은 단위로 쪼개서 병렬 처리
class SumTask extends RecursiveTask<Long> {
private long[] array;
private int start, end;
@Override
protected Long compute() {
if (end - start <= 1000) {
// 작은 단위 → 직접 계산
long sum = 0;
for (int i = start; i < end; i++) sum += array[i];
return sum;
}
// 큰 단위 → 둘로 쪼개서 병렬 처리
int mid = (start + end) / 2;
SumTask left = new SumTask(array, start, mid);
SumTask right = new SumTask(array, mid, end);
left.fork(); // 다른 코어에서 실행
return right.compute() + left.join(); // 결과 합산
}
}
Parallel Stream
List<Integer> numbers = List.of(1, 2, 3, 4, 5 ...);
// 일반 Stream - 순차 처리
numbers.stream()
.map(n -> n * 2)
.collect(toList());
// Parallel Stream - 멀티코어 병렬 처리
numbers.parallelStream() // O 내부적으로 Fork/Join 사용
.map(n -> n * 2)
.collect(toList());
CompletableFuture
// 여러 작업을 병렬로 실행 후 결과 합산
CompletableFuture<String> task1 =
CompletableFuture.supplyAsync(() -> "결과1"); // Core1에서 실행
CompletableFuture<String> task2 =
CompletableFuture.supplyAsync(() -> "결과2"); // Core2에서 실행
// 둘 다 완료되면 합산
CompletableFuture.allOf(task1, task2)
.thenRun(() -> System.out.println(task1.get() + task2.get()));
병렬성이 무조건 빠른 건 아니다
병렬 처리 비용
├── 작업 분할 비용
├── 스레드 간 통신 비용
├── 결과 합산 비용
└── 컨텍스트 스위칭 비용
작업량이 적으면
병렬 처리 비용 > 성능 향상 → 오히려 느려짐 X
작업량이 충분히 클 때만 병렬 처리가 유리 O
동시성 vs 병렬성 정리
| 항목 | 동시성 | 병렬성 |
|---|---|---|
| 코어 수 | 1개 이상 | 반드시 2개 이상 |
| 실행 방식 | 번갈아 실행 | 진짜 동시 실행 |
| 목적 | 응답성 향상 | 처리 속도 향상 |
| 적합한 작업 | I/O 대기, 네트워크 | CPU 집약적 연산 |
| 예시 | 웹 서버 요청 처리 | 이미지 렌더링, 데이터 분석 |
동시성은 "여러 일을 잘 관리", 병렬성은 "여러 일을 동시에 처리" 입니다. 실무에서는 대부분 두 개념이 함께 사용됩니다. (멀티코어 + 스레드 관리)