동시성 개요
개념 정리
- 동시성 : 한 번에 두 가지 이상의 작업을 수행
- 멀티스레딩 : 다수의 실행 스레드를 사용하는 동시성의 한 형태
- 병렬 처리 : 많은 작업을 여러 스레드에 나눠 수행하는 멀티스레딩의 한 형태
- 비동기 프로그래밍 : 불필요한 스레드의 사용을 피하기 위해 퓨처나 콜백을 사용하는 동시성의 한 형태
- 리액티브 프로그래밍 : 앱이 이벤트에 대응하는 방식
병렬 프로그래밍
병렬 프로그래밍은 데이터 병렬과 작업 병렬로 나눌 수 있다.
- 데이터 병렬 : 처리해야 할 데이터들을 다른 데이터들과 독립적으로 처리할 수 있을 때 해당된다.
- 작업 병렬 : 작업 풀에 있는 작업들이 다른 작업과 독립적일 때 해당. 모든 작업이 독립적이면 동기화가 필요 없어지므로 병렬 처리가 극대화된다.
스레드 풀
스레드 풀은 알아서 작업을 잘 처리해준다. 파티셔너 라는 녀석이 작업을 작업 스레드에 분배해준다. 스레드 풀은 하나의 작업 큐를 지니며, 각 스레드도 작업 큐를 지닌다. 스레드 풀 스레드가 추가 작업을 큐에 넣으면 우선 자기 자신의 큐에 넣는데, 이것은 캐시를 잘 활용하고자 함이다. (보통 자기 작업과 연관이 있으므로) 할 일이 없는 스레드는 다른 스레드의 큐에서 작업을 가져온다.
스레드 풀에서는 작업의 길이가 성능에 영향을 미칠 수 있다. 작업이 너무 짧으면 스레드 풀이 작업을 스케줄링하는 데 드는 부담이 크다. 작업의 길이가 너무 길면 스레드 풀이 동적으로 작업의 균형을 맞추기 어렵다. 만약 작업이 매우 짧다면 성능이 급격히 떨어질 수 있으니 이때는 Parallel 형식 또는 PLINQ를 사용하는 쪽이 더 좋다. 얘네는 기본적으로 파티셔너가 작업의 길이 문제를 알아서 처리해준다.
리액티브 프로그래밍
옵저버블 스트림이라 불리는 이벤트를 발생시키는 스트림이 있고 이를 구독하는 형식이다.
구독은 핫 옵저버블과 콜드 옵저버블로 나눌 수 있다.
- 핫 옵저버블 : 구독이 없어도 발생하는 이벤트. (ex. 마우스 포인트 이벤트)
- 콜드 옵저버블 : 구독을 시작해야 발생하는 이벤트 (ex. Http 요청은 구독을 시작해야 함)
컬렉션
동시성 프로그래밍에서는 concurrent 컬렉션이나 immutable 컬렉션이 유용하다.
concurrent 컬렉션은 스냅샷이라는 개념을 이용하여 하나의 스레드가 값을 보는동안 다른 스레드가 값을 수정하거나 삭제할 수 있게 한다.
immutable 컬렉션은 실제로 수정할 수 없으며 수정을 하려하면 새로운 컬렉션이 생성된다. (COW) immutable 컬렉션은 수정할 수 없기 때문에 동기화도 필요 없다.