이번 포스팅에선 멀티쓰레드 개념에 대해서 기초부터 조금 더 공부하면서 통찰력을 기르기 위해 작성한 게시글이다.
실행 파일을 실행시키면 하나의 Process가 생성됨
그 Process안에 Thread가 만들어짐
이 Thread를 보통 Main Thread라고 부름
한 Process안에 Main Thread외에 다른 Thread가 있으면 Multi Thread임
하지만 Thread간에 아무런 메모리 공유가 일어나지 않는다면 Multi Thread라고 부르기 애매함
그렇다면 ?
Thread끼리는 메모리 공유가 됨
Process끼리는 메모리 공유가 안됨
모든 Thread가 하나의 Queue를 공유함
괜찮나요? 당연히 안 괜찮음
이런 문제를 피하는 제어를 배타제어라고 함
처음부터 망가뜨릴수 없는 오브젝트를 만든다. Concurrent가 Prefix로 붙는 클래스들을 사용함
Concurrent클래스가 어떻게 구현되어 있느냐에 따라 성능저하가 발생할수 있음
일반클래스도 Read는 Thread Safe한 경우가 있음 Write는 한 Thread에서만 하고 Read를 여러 Thread가 하는 경우 유용함
솔직히 위의 보기는 처음보는거라 느낌만 알겠는 수준이고 나에게 익숙한 건 아래에 lock 방식에 나올 것 이다.
특정 코드 구간을 반드시 한 Thread만 실행하도록 막음
크리티컬 섹션이라고도 부름
Lock을 건 코드의 구간의 실행시간이 길수록 성능저하가 발생함. 최악의 경우엔 차라리 Single Thread가 나음
그래서 One Process, One Thread Architecture가 나옴
redis 초기에 멀티쓰레드 지원을 하지않을 때 One Process, One Thread 임에도 불구하고 빠르기 때문에 많은 개발자가 애용하였다.
Lock을 사용하지 않고 배타제어를 하는데 목적을 두고 있음
여기서 부턴 파다보면 한도 끝도 없음
Interlocked.Increment(), Atomic Operation, Lock-Free알고리즘, Non-Blocking 알고리즘, CAS(compare and set) 검색 해보자
Process끼리는 메모리 공유가 안되기 때문에 통신을 해야 됨
HTTP도 좋고 TCP도 좋고 편한거 쓰면 됨
MSA (MicroService Architecture)를 지향하는 현대 사회에서 Process간의 통신은 필수
서버 머신 한대의 성능에는 한계가 있음. 그래서 Scale-Out이 필수
하나의 Process를 2대의 장비로 돌릴수 있음? 없음
서버 Architecture를 구상하는 입장에선 Process 하나가 작은 기능을 담는게 훨씬 유리
그래서 One Process, One Thread가 설득력이 있음
Process간의 통신을 위해 프로토콜을 만들고 통신하는 코드를 만들고 하는 작업이 여간 귀찮은게 아님
서로 다른 언어를 써서 만든 Process 끼리라면? 서로 패킷 모델을 주고 받는것도 엄청 스트레스
그래서 나온게 Google Protobuf나 Apache Avro
Json Format을 사용해도 됨
하지만 필드가 하나 추가됐다면? 어떻게 상대방에게 알려줄 것인가? 오타라도 있다면? 디버깅 하기 짜증남
Protobuf를 쓰면 편안
Redis의 특정 Key에 데이터를 넣고 Pub/Sub을 이용하는 방법도 있음
빠르게 통신할 필요가 없다면 AWS SQS같은 Queue에 넣고 데이타가 추가됐을때 특정 Topic으로 Event를 받는 방법도 있음
데이터를 보내려는 서버가 알아서 다른 서버에 보내주는게 아니라 올려놓고 알아서 가져가라 라는 방식