diff --git "a/11\354\236\245_\353\217\231\354\213\234\354\204\261/Item 84 \355\224\204\353\241\234\352\267\270\353\236\250\354\235\230 \353\217\231\354\236\221\354\235\204 \354\212\244\353\240\210\353\223\234 \354\212\244\354\274\200\354\244\204\353\237\254\354\227\220 \341\204\200 d4c3f544c65f432197cf39cdeda9e590.md" "b/11\354\236\245_\353\217\231\354\213\234\354\204\261/Item 84 \355\224\204\353\241\234\352\267\270\353\236\250\354\235\230 \353\217\231\354\236\221\354\235\204 \354\212\244\353\240\210\353\223\234 \354\212\244\354\274\200\354\244\204\353\237\254\354\227\220 \341\204\200 d4c3f544c65f432197cf39cdeda9e590.md" new file mode 100644 index 0000000..3edcc12 --- /dev/null +++ "b/11\354\236\245_\353\217\231\354\213\234\354\204\261/Item 84 \355\224\204\353\241\234\352\267\270\353\236\250\354\235\230 \353\217\231\354\236\221\354\235\204 \354\212\244\353\240\210\353\223\234 \354\212\244\354\274\200\354\244\204\353\237\254\354\227\220 \341\204\200 d4c3f544c65f432197cf39cdeda9e590.md" @@ -0,0 +1,81 @@ +# Item 84. 프로그램의 동작을 스레드 스케줄러에 기대지 말라 + +생성 일시: 2023년 1월 2일 오후 9:11 + +여러 스레드가 실행중이라면 운영체제의 스레드 스케줄러가 어떤 스레드를 얼마나 오래 실행할지를 결정하는데, 정상적인 운영체제라면 이 작업을 공정하게 수행하게 해준다. + +그렇지만, 운영체제마다 스케줄링 정책은 다르다. 그래서 잘 작성된 프로그램은 스케줄링에 영향을 받지 않으며 정확성이나 성능이 스케줄러따라 달라져선 안된다. + +> 이식성 좋은 프로그램을 만드는 가장 좋은 방법 +> + +평균적인 실행 가능 스레드 수를 프로세서 수보다 지나치게 많아지지 않도록 하는 것이다. + +실행 준비가 된 스레드들은 작업을 완료할 때까지 계속 실행되도록 만들어주자. + +→ 스레드 스케줄링 정책이 아주 상이한 시스템에서도 동작이 크게 달라지지 않는다. + +실행가능한 스레드 수와 전체 스레드 수는 구분해야 한다. + +### 실행가능한 스레드 수를 적게 유지하는 기법 + +각 스레드가 무언가 유용한 작업을 한 이후에 다음 일거리가 생길 때까지 대기하도록 하는 것 + +**스레드는 당장 처리해야할 작업이 없다면 실행되선 안된다.** + +→ 스레드 풀을 적절하게 설정 후 작업은 짧게 유지하면 됨. + +### 바쁜 대기상태가 되지 않아야 한다 + +공유 객체 상태가 바뀔때까지 쉬지 않고 검사해서는 안된다. + +바쁜 대기는 스레드 스케줄러의 변덕에 취약하고, 프로세스에 큰 부담을 준다. + +CountDownLatch를 잘못 구현한 코드 + +```java +public class SlowCountDownLatch { + private int count; + + public SlowCountDownLatch(int count) { + if (count < 0) { + throw new IllegalArgumentException(count + " < 0"); + } + this.count = count; + } + + public void await() { + while (true) { + synchronized(this) { + if (count == 0) { + return; + } + } + } + } + + public synchronized void countDown() { + if (count != 0) { + count--; + } + } +} +``` + +하나 이상의 스레드가 필요없이 실행 가능한 상태인 시스템이라면 흔하게 볼 수 있는 과정이다. + +이런 시스템은 성능과 이식성이 떨어질 수 있다. + +특정 스레드가 다른 스레드들보다 CPU 시간을 충분히 얻지 못하여 간신이 돌아가는 프로그램에도 `Thread.yield` 를 써서 고치려는 유혹을 떨쳐내야 한다. + +`Thread.yield` 는 테스트할 수단도 없다. + +우선순위를 주는 방법도 있지만, 이마저도 위험이 존재한다. + +그리고 스레드 우선순위는 자바에서 이식성이 가장 나쁜 특성에 속한다. + +## 정리 + +단순하게 생각해보면 어떻게 실행되어도 항상 동일한 결과를 나타내주면 된다는 뜻인것 같다. + +그래서 스레드를 튜닝할 게 아니라 정말 근본적인 문제가 뭐 때문인지를 파악하는게 중요할 것이다. \ No newline at end of file