Commentaries
there are rather lots of idioms. Approaches that systems programmers
commonly use include the following:
- A background thread that has a single job and periodically wakes up to do it.
- General-purpose worker pools that communicate with clients via task queues.
- Pipelines where data flows from one thread to the next, with each thread doing a
little of the work.
- Data parallelism, where it is assumed (rightly or wrongly) that the whole com‐
puter will mainly just be doing one large computation, which is therefore split
into n pieces and run on n threads in the hopes of putting all n of the machine’s
cores to work at once.
- A sea of synchronized objects, where multiple threads have access to the same
data, and races are avoided using ad hoc locking schemes based on low-level
primitives like mutexes. (Java includes built-in support for this model, which was
quite popular during the 1990s and 2000s.)
- Atomic integer operations allow multiple cores to communicate by passing infor‐
mation through fields the size of one machine word. (This is even harder to get
right than all the others, unless the data being exchanged is literally just integer
values. In practice, it’s usually pointers.)
- 단일 작업을 가지고 주기적으로 깨어나서 그것을 수행하는 백그라운드 스레드.
- 클라이언트와 작업 대기열을 통해 통신하는 범용 워커 풀.
- 데이터가 한 스레드에서 다음 스레드로 흐르며, 각 스레드가 작업의 일부를 수행하는 파이프라인.
- 컴퓨터가 주로 하나의 큰 계산만을 수행한다고 가정하고 (옳든 그르든), 그 계산을 n개의 조각으로 나누어 n개의 스레드에서 실행하여 머신의 모든 n개의 코어를 한 번에 활용하려는 데이터 병렬성.
- 여러 스레드가 동일한 데이터에 접근하며, 경합 조건을 피하기 위해 뮤텍스와 같은 저수준의 원시 요소를 기반으로 하는 임의의 락킹 스키마를 사용하는 동기화된 객체의 바다. (Java는 1990년대와 2000년대에 상당히 인기가 있었던 이 모델에 대한 내장 지원을 포함합니다.)
- 여러 코어가 한 머신 워드 크기의 필드를 통해 정보를 전달함으로써 통신할 수 있게 하는 원자적 정수 연산. (이는 교환되는 데이터가 문자 그대로 정수 값인 경우를 제외하고는 다른 모든 것보다도 올바르게 처리하기가 더욱 어렵습니다. 실제로는, 교환되는 데이터가 보통 포인터입니다.)
이번 챕터에서 다루어지는 것
- Fork-join parallelism
- Channels
- Shared mutable state
Fork-Join Parallelism
The simplest use cases for threads arise when we have several completely independent
tasks that we’d like to do at once.