복잡한뇌구조마냥

[JAVA] Effective Java - 프로그램의 동작을 스레드 스케줄러에 기대지 말라 (84) 본문

BE/JAVA

[JAVA] Effective Java - 프로그램의 동작을 스레드 스케줄러에 기대지 말라 (84)

지금해냥 2025. 9. 7. 15:23

요약

  • 스레드 스케줄링 정책은 운영체제마다 다르다.
  • 잘 작성된 프로그램은 스케줄러의 정책 차이에 영향받지 않아야 한다.
  • Thread.yield()스레드 우선순위는 의존해서는 안 되며, 힌트 정도로만 쓰인다.
  • **Busy waiting(바쁜 대기)**은 절대 금물.
  • 실행 가능한 스레드 수는 프로세서 수보다 과도하게 많아서는 안 된다.
  • 목표: 이식성, 견고성, 성능을 모두 확보하는 프로그램.

1. 왜 스레드 스케줄러에 의존하면 안 되는가?

  • 스레드 스케줄링은 운영체제마다 정책이 다르다.
  • 어떤 JVM에서는 잘 동작하던 코드가 다른 JVM이나 OS에서는 느리거나 멈출 수 있음.
  • → 즉, 스케줄러에 기대는 프로그램은 이식성이 떨어진다.

2. 좋은 프로그램의 특징

  • 실행 가능한 스레드 수를 프로세서 수와 비슷하게 유지.
  • 스레드는 작업이 있을 때만 실행하고, 없으면 대기.
  • 실행 중인 스레드는 작업을 끝마칠 때까지 실행되도록 설계.
  • 이렇게 하면 스케줄링 정책이 달라져도 프로그램 동작이 크게 달라지지 않는다.

3. 피해야 할 나쁜 습관

(1) Busy Waiting (바쁜 대기)

  • 스레드가 해야 할 작업이 없는데도 계속 실행 상태를 유지하며 루프를 도는 것.
  • 예: 공유 객체의 상태 변화를 기다리며 쉬지 않고 검사.
  • 문제점:
    • CPU 자원 낭비
    • 다른 작업 방해
    • 스케줄러 정책에 따라 동작이 불안정

👉 해결: wait/notify, CountDownLatch, BlockingQueue동기화 도구를 사용.


(2) Thread.yield()

  • 어떤 스레드가 충분히 실행되지 못해 Thread.yield()로 양보하는 코드 → 위험.
  • JVM마다 결과가 다르다:
    • 어떤 JVM에선 빨라질 수 있지만,
    • 다른 JVM에선 효과 없고,
    • 또 다른 JVM에선 더 느려질 수도 있다.
  • 테스트할 방법도 없음.
    👉 Thread.yield()는 성능 개선/문제 해결용으로 쓰면 안 된다.

(3) 스레드 우선순위

  • 자바에서 가장 이식성이 떨어지는 특성 중 하나.
  • 우선순위를 조정해서 반응속도를 높이는 건 극히 드문 상황에서만 가능.
  • 근본적인 원인을 해결하지 않고 우선순위로 땜질하면 문제는 반복 발생.
    👉 스레드 우선순위는 스케줄러에 주는 힌트 수준일 뿐, 로직 보장 수단이 아니다.

4. 올바른 접근

  • 스케줄러에 의존하지 않는 방식으로 설계해야 한다.
  • 실행 가능한 스레드는 필요할 때만 존재하도록 하고, 작업 없으면 대기 상태로.
  • 동시성 유틸리티(java.util.concurrent 패키지) 적극 활용.
  • 서비스 품질 향상을 위해 yield나 우선순위를 쓰는 건 괜찮지만,
    프로그램이 돌아가도록 만드는 수단으로는 절대 사용하지 말라.

✅ 결론

스레드 스케줄러의 정책은 제어할 수 없고 JVM/OS마다 다르다.
따라서 프로그램은 스케줄러에 기대지 않고 자체적으로 견고하게 동작해야 한다.

  • Busy waiting 금지
  • Thread.yield와 스레드 우선순위 의존 금지
  • 실행 가능한 스레드 수를 적절히 유지

올바른 동시성 도구와 설계로 이식성, 성능, 안정성을 확보하라.

LIST