스레드를 무분별하게 생성하는 위험을 피하려면 자바 동시성 프레임워크에서 제공하는 ExecutorService 같은 기능을 사용하는 것이 좋다. ExecutorService는 더 구조화된 방식으로 스레드를 사용할 수 있게 해준다. ExecutorService는 단지 동시에 실행되는 스레드의 수를 제어하는 데 그치지 않고 스레드의 생애주기를 관리해서 스레드를 효율적으로 재사용 할 수 있게 해준다.
그러나 이그제큐터 프레임워크의 한계 중 하나로, 캐시 일관성 유지 부하와 거짓 공유 위험이 있다.
스레드 풀에 제출된 태스크는 메인 스레드 말고 서로 다른 CPU 코어에서 실행되는 다른 스레드에서 실행된다. 코어마다 캐시 상태가 달라질 수 있고 그 결과 캐시 일관성 프로토콜(cache coherence protocol)이 코어들 사이에서 캐시 일관성을 유지하기 위해 계속해서 캐시 데이터를 무효화하고 동기화해야 하므로 오히려 성능이 저하될 잠재적 위험이 생긴다.
[캐시 일관성 프로토콜]
최근에 만들어진 CPU는 MESI 프로토콜 또는 MOESI 프로토콜과 같은 캐시 일관성 프로토콜을 사용해서 각 CPU 코어가 메모리 상태를 일관성 있게 볼 수 있도록 보장한다. 하나의 CPU 코어가 캐시 라인에 데이터를 저장하면, 캐시 일관성 프로토콜에 의해 다른 CPU의 캐시 라인도 무효화되거나 업데이트된다. 이는 데이터 정합성을 보장하지만 여러 CPU 코어의 캐시 라인을 동일하게 유지하기 위해 빈번하게 캐시 라인을 무효화하거나 업데이트해야 하므로 성능에 부담을 줄 수 있다.
요즘 CPU는 데이터 접근 속도를 높이기 위해 L 캐시를 갖고 있다. L 캐시는 적은 양의 데이터를 저장하며, CPU가 데이터를 필요로 할 때 메인 메모리가 아닌 CPU 안에 있는 캐시에서 가져올 수 있으므로 훨씬 빨리 가져올 수 있다. 이처럼 캐시에 저장되는 일정 크기의 데이터를 캐시 라인(cache line)이라고 부르며, 이 캐시 라인을 활용해 전체적인 성능을 획기적으로 향상할 수 있다.
- 주로 L1, L2 캐시는 코어별로 존재하고, L3 캐시는 여러 코어가 공유한다.

- CPU는 캐시에 데이터를 1바이트 단위로 가져오지 않고, 64 바이트 단위로 가져온다. 그리고 이 묶음을 캐시 라인이라고 한다.
다수의 태스크가 동시에 실행될 때 2개의 순차적인 태스크 각각에서 사용되는 데이터가 동일한 캐시 라인에 저장될 수도 있다. 그 2개의 태스크가 동일한 CPU에서 실행된다면 앞선 태스크를 실행하면서 캐시에 저장된 데이터를 그다음 태스크에서 바로 사용할 수 있으므로 메인 메모리를 다시 찾을 필요가 없어져서 두 번째 태스크는 미미하지만 더 빨리 실행될 수 있다.
하지만 두 태스크가 서로 다른 CPU 코어에서 실행된다면, 첫 번째 태스크를 실행하는 CPU에서 캐시 데이터 변경이 발생하는 경우 두 번째 태스크를 실행하는 CPU도 캐시 라인을 무효화하고 전체 캐시 라인을 메인 메모리나 다른 코어의 캐시에서 가져와야 한다.
예를 들어, CPU 코어 1과 코어 2가 각각 자신의 캐시 라인데 데이터를 캐싱해뒀는데, 같은 변수를 캐싱했다고 가정하자. 64 바이트의 묶음 데이터를 캐싱하기 때문에, 두 코어 모두 num1 변수와 num2 변수를 캐싱했다. 이때 코어 1은 num2 값을 쓰지 않더라도, 코어 2가 num2 값을 변경했을 때 코어 1은 자신의 연산을 멈추고 num2 값을 다시 받아오는 동기화 작업을 진행한다. (정확히는 num2 변수만이 아닌, 캐시라인 단위로 invalidation)

코어 1이 num2 값을 사용하지도 않는데 동기화가 일어난다. 따라서 이를 거짓 공유(false sharing)이라고 한다. 거짓 공유 현상은 서로 다른 스레드가 우연히 동일한 캐시 라인에 저장된 서로 다른 변수를 수정할 때 발생한다.
이를 해결하는 방법은 패딩(padding)을 이용해 데이터를 64 바이트로 채워주어, 필요한 데이터만 캐싱하는 것이다.

자바로 돌아와서 정리하자면, 이그제큐터 프레임워크를 사용하면 각 태스크가 서로 다른 CPU 코어에서 병렬로 실행될 수 있다. 그리고 이로 인해 CPU 코어의 캐시 메모리 간 캐시 라인 무효화와 동기화가 빈번히 발생할 수 있어서, 이그제큐터 프레임워크 사용 시 전반적인 성능에 악영향을 끼칠 수 있다.
Reference
- 모던 자바 동시성 프로그래밍 | ANM 바즐루어 라만 | 책만
- https://hwan-shell.tistory.com/230