-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[#84][A팀] 프로그램의 동작을 스레드 스케줄러에 기대지 말라
[#84][A팀] 프로그램의 동작을 스레드 스케줄러에 기대지 말라
- Loading branch information
Showing
1 changed file
with
114 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
# item 84. 프로그램의 동작을 스레드 스케줄러에 기대하지 말라 | ||
|
||
# 🧭 스레드 스케줄러 | ||
|
||
> 여러 스레드가 실행 중이면 운영체제의 **스레드 스케줄러**가 어떤 스레드를 얼마나 오래 실행할지 정한다. | ||
## 스레드 스케줄러란? | ||
|
||
![Untitled](https://user-images.githubusercontent.com/42836576/113815194-bd89e780-97ad-11eb-939c-f41ce7994239.png) | ||
|
||
- **스레드의 실행 시점을 관리**하는 역할을 한다. | ||
- 언제 실행 가능한 상태로 움직여야할지 | ||
- 언제 실행중인 상태를 종료해야할지 | ||
- 종료했을 때 스레드를 어디로 보내야할지 | ||
- ... | ||
- 사용자가 제어할 수 없다. | ||
- 제한된 자원을 여러 프로세스가 효율적으로 사용하도록 다양한 정책(Policy)을 가지고 할당한다. → 즉, **운영체제**마다 달라질 수 있다. | ||
|
||
> 정확성이나 성능이 스레드 스케줄러에 따라 달라지는 프로그램이라면 다른 플랫폼에 이식하기 어렵다. | ||
```jsx | ||
// 이식이 어려운 프로그램을 만들고 있는 🐱💻 | ||
🐱💻 : 이 프로그램은 A 스케줄링 정책에 맞춰 작성해야지! | ||
macOS 기반에서 A 정책은 우선순위가 높으니까 제대로 돌아갈거야! | ||
|
||
// 이식성이 좋은 프로그램을 만들고 있는 🐰 | ||
🐰 : 프로세스 수가 n개니까 스레드 개수가 너무 많아지지 않게 조절해야겠다. | ||
(기본 최대값은 프로세스당 250개의 스레드) | ||
``` | ||
|
||
# 🦉 실행 가능한 스레드 수를 적게 유지하기 | ||
|
||
실행 가능한 스레드 = 대기(waiting) 상태인 스레드 | ||
|
||
## 1. 당장 처리해야할 작업이 없다면 실행하지 않기 | ||
|
||
- 스레드 풀 크기를 적절히 설정하고, 작업은 짧게 유지해야 한다. | ||
- 단, 너무 짧으면 오히려 작업 분배에 부담이 가서 성능을 떨어뜨릴 수 있다. | ||
- **바쁜 대기(busy waiting)** 상태가 되면 안된다. | ||
- 기다리는 스레드가 공유 자원을 사용할수 있는지 없는지 계속해서 무한 루프를 돌면서 조건문을 체크하는 방식 | ||
|
||
```jsx | ||
// 바쁜 대기 버전 CountDownLatch 구현 | ||
public class SlowCountDownLatch { | ||
privateint count; | ||
public SlowCountDownLatch(int count) { | ||
if (count < 0) | ||
throw new IllegalArgumentException(count + " < 0"); | ||
this.count = count; | ||
} | ||
public void await() { // 바쁜 대기 중 (so bad ~~~) | ||
while (true) { | ||
synchronized(this) { | ||
if (count == 0) | ||
return; | ||
} | ||
} | ||
} | ||
|
||
public synchronized void countDown() { | ||
if count != 0) | ||
count--; | ||
} | ||
} | ||
``` | ||
|
||
- 스레드 스케줄러의 변덕에 취약하다. | ||
- 프로세서에게 부담을 주기 때문에 다른 유용한 작업이 실행될 기회를 박탈한다. | ||
|
||
→ **성능**과 **이식성**이 떨어진다. | ||
|
||
# 🔥 하지말아야 할 것들 | ||
|
||
## 1. Thread.yield | ||
|
||
### 가 뭐지? | ||
|
||
- 다른 스레드에게 실행을 양보하는 메서드 | ||
|
||
```jsx | ||
🐱💻 : A 스레드에 비해 B 스레드는 CPU 시간이 적으니까, yield()를 사용해서 시간을 조절하자! | ||
``` | ||
|
||
### 하지말자 | ||
|
||
- 오히려 성능이 나빠질 수도 있다. | ||
- **테스트할 수단도 없다.** | ||
|
||
→ 차라리 애플리케이션 구조를 바꿔 동시 대기 상태의 스레드 수가 적어지도록 하자 | ||
|
||
## 2. Thread Priority | ||
|
||
### 가 뭐지? | ||
|
||
- 스레드의 우선순위 | ||
|
||
```jsx | ||
🐱💻 : 스레드 스케줄링 전략은 우선순위에 따라 바뀌니까 우선순위를 조절해야겠다! | ||
``` | ||
|
||
### 하지말자 | ||
|
||
- 이미 잘 동작하는 프로그램의 서비스 품질을 높이기 위해 드물게 쓰일 수는 있다. | ||
- 그러나 거의 동작하지 않는 프로그램을 "고치기 위해" 사용하면 절대 안 된다. | ||
- 스레드 우선순위는 이식성이 가장 나쁜 특성에 속한다. | ||
|
||
→ 진짜 원인을 찾아 수정하자 | ||
|
||
# 🥱 결론 | ||
|
||
- 프로그램의 동작을 스레드 스케줄러에 기대지 말자 | ||
- Thread.yield와 스레드 우선순위에 의존하지도 말자 |