분할 후 정복 방식으로 태스크 처리
Work-Stealing 매커니즘
<aside>
고정된 개수의 스레드 유지.
대기 중인 유휴 스레드가 공유 큐에 있는 태스크를 가져감
But, 이렇게 하면 스레드가 태스크를 가져가기 위해 경쟁하게 되고 오버헤드 발생함.
RecursiveTask
fork()
compute(), join()
if (작업이_충분히_작다면) {
return 직접_계산();
} else {
MyTask left = new MyTask(절반);
MyTask right = new MyTask(나머지);
left.fork(); // 비동기 실행
return right.compute() + left.join(); // 직접 계산 + 결과 합치기
return left.join() + right.compute(); // 잘못된 코드
}
compute()가 join() 뒤에 위치한다면?
정상적으로 동작하지 않음.
left에 대한 fork()후 곧바로 join()으로 인해 현재 스레드는 블로킹되고 right부분을 그 이후에 처리하게 되므로 병렬 이점이 사라짐.

워커 스레드와 도둑 스레드가 동시에 같은 큐에 접근한다면?
경합이 발생함.
그래서 이를 최소화하기 위해 두 스레드가 큐의 서로 다른 끝에서 태스크를 가져가도록 설계
락을 획득하는 대신, 변수의 현재 값을 예상 값과 비교하고, 두 값이 일치할 때만 새 값으로 교체
→ ForkJoinPool도 이를 활용해서 큐 관리함
→ Java의 VarHandle로 원자적 연산을 사용해 저수준에서 변수에 접근할 수 있음
블로킹이 없고 락을 획득하고 해제하는 데 드는 오버헤드를 줄일 수 있음.
경합이 심하지 않을 때 효율적