예전엔 동시성이 없어 어떤 프로그램을 다운받을 경우, 사용자가 다른 일을 못했던 시절이 있다. 또한, 동시성이 없이는 하드웨어 리소스도 낭비었다. 예를 들어 1초에 7천억번의 명령을 처리할 수 있는 기회를 허비할수도.
B비선점형 멀티태스킹
- 프로그램 A가 자기의 리소스를 쓰고, 더 이상 필요 없을때 프로그램 B에게 리소스를 준다.
- 누군가는 자원을 독점하고 죽어버리는 경우가 많아 현실에선 잘 안씀.
중재자를 두자 → 중재자 : 운영체제 → 선점형 멀티태스킹
선점형 멀티태스킹
Ring 0~3가 존재한다면, Ring 0 을 가진 중재자 = 운영체제
- Ring 레벨이 높은 곳에서 낮은 곳으로만 접근 가능
- Ring 0 → Ring 3 접근 가능. Ring 3 → 0 접근 불가.
- 운영체제는 어플리케이션에게 어떤 영향을 줄 수 있지만, 어플리케이션은 운영체제에게 영향을 줄 수 없어 시스템 콜 등의 방법으로 간접 접근.
- 운영체제 커널, 하드웨어 드라이버는 보통 Ring 0 의 특권을 가짐
- 시스템 종료, 인터럽트 활성화/비활성화, 하드웨어 입출력
- 시분할 등 방법으로 자원을 나눔
- 각각의 프로세스가 운영체제에 의해서 공정하게 시간을 분배 받아서 수행될 수 있기 때문에 → 여러 프로그램들이 동시에 수행될 수 있음
- 코드, 데이터, 힙, 스택 등의 자료구조를 가짐
- 일반적으론 프로그램들은 하나의 프로세스가 있다면 그 프로그램 내에서 여러 개의 스레드를 가지고 상호작용을 하며 돌아갈 수 있다.
- 윈도우에선 하나의 프로세스를 만들 때마다 많은 리소스가 필요. 프로세스 생성이 느림.
- 리눅스에서는 프로세스와 스레드 만드는데 차이가 나지 않음(COW 방식)
SMP (Symmetric Multiprocessor) & 가시성
- 여러 프로세스가 하나의 메모리를 쓰는 모델
- 여러 프로세스가 있기에 물리적으로 여러일을 동시에 사용하는 일이 가능해짐
- 하지만 프로그래밍 이슈가 범람함
- 가시성 문제
- 여러 코어가 개별 캐시를 사용할때.
- 락이나 메모리 베리어가 필요할 수 있음
- 거짓 공유 & 데이터를 갱신 문제
- 캐시는 캐시라인의 집합이기에, 캐시라인을 통째로 한번에 교체한다. 데이터 하나만 교체할 수 없음.
- 인접한 캐시라인은 한번에 한 코어에서만 접근 가능
- 두개의 코어를 쓰는 의미가 없어짐 (가짜 공유)
비동기 병렬성에 필요성이 많아짐
→ 하지만 함정이 많음
→ 콜백, RxJava 가 이 문제들을 해결하기 위해 노력함
하지만 콜백을 쓰는경우, 코드 깊이가 늘어나 가독성이 안 좋아지고 관리가 어렵다.
RxJava 를 쓰는 경우 코드가 좀더 깔끔하지만, 항상 스트림을 써야한다는게 문제라서 가독성 및 유지보수가 어렵다.
코드를 순차적으로 짰을때와, RxJava 비동기로 짤땐 또 다른코드가 되어서
→ 동기 or 비동기, 동시성 or 순차적 인 조건만 달라졌을 뿐인데, 코드 전체가 바뀌게 되는 점이 아쉽다.
코루틴은 동시성이냐 동시성이 아니냐에 따라 코드가 달라지지 않는다.
콜백과 Rx 보다 훨씬 간결해짐을 느끼기에 추천한다.
코루틴은 비동기와 병렬성을 순차적으로 짤 수 있는 코드 방법을 제공.
플로우는 비동기와 병렬성을 스트림의 형태로 풀 수 있는 형태를 보여준다.