본문 바로가기
Book/Pragmatic Programmer

제 6장 동시성

by 라바킴 2022. 3. 29.
" 동시성은 필수다. 세상은 비동기적이기 때문이다. "

TIL (Today I Learn)

  • Assignment 10
  • 2022-03-29 ~ 2022-03-30


오늘 읽은 범위

  • 6장 동시성
    • Topic 33 시간적 결합 깨트리기
    • Topic 34 공유 상태는 틀린 상태
    • Topic 35 액터와 프로세스
    • Topic 36 칠판

3줄 요약

  • ‘동시성 concurrency’은 둘 이상의 코드 조각이 실행될 때 동시에 실행 중인 것처럼 행동하는 것이고,
    ‘병렬성 parallelism’이란 실제로 동시에 실행되는 것이다.
  • 동시성은 소프트웨어 동작 방식이고, 병렬성은 하드웨어가 하는 것이다.
  • 공유 상태는 틀린 상태다.

 

" 동시성은 ‘병행성’이라고도 한다. (Concurrency) "

 


책에서 기억하고 싶은 내용을 써보세요

Topic 33 시간적 결합 깨트리기

  • ‘시간적 결합 temporal coupling’은 당면한 문제 해결에 꼭 필요하지 않은 일 처리 순서를 코드가 강제할 때 생긴다. 
  • 활동 다이어그램을 사용하면 동시에 수행할 수 있는데도 아직 동시에 하고 있지 않은 활동들을 찾아내서 병렬성을 극대화할 수 있다.

 

Topic 34 공유 상태는 틀린 상태

  • 공유 상태는 틀린 상태다.
  • 세마포어 semaphore는 단순히 한 번에 한 사람만이 가질 수 있는 무언가다.
  • 불규칙한 실패는 동시성 문제인 경우가 많다.
  • 언어 자체에 동시성 지원이 들어 있는 언어도 있다. 예를 들어 러스트 Rust는 데이터의 소유권이라는 개념을 강제한다.
    • 변경 가능한 데이터 조각 은 어느 한 시점에 단 하나의 변수나 매개 변수만 참조를 가질 수 있다.

 

 

Topic 35 액터와 프로세스

  • 액터 모델에서는 프로세스들이 독립적으로 수행되며 서로 데이터를 공유하지 않는다.
    • 공유 상태 없는 동시성을 위하여 액터를 사용하라.
  • '액터'는 자신만의 비공개 지역 상태 state를 가진 독립적인 가상 처리 장치 virtual processor
    • 액터는 우편함mailbox을 하나씩 보유
    • 우편함에 메시지가 도착하면 액터가 깨어나면서 메시지를 처리
    • 처리가 끝나면 우편함의 다른 메시지를 처리
    • 만약 우편함 이 비어 있으면 다시 잠듦
    • 모든 메시지는 일방향 (답장이란 개념 없음)
    • 답장이란 개념은 없음
    • 한 번에 하나의 메시지만 처리
  • '프로세스'는 본래 더 일반적인 가상 처리기
    • 보통 운영 체제가 동시성을 지원하기 위하여 구현
    • 마치 액터처럼 동작하 도록 관례를 만들어 제한적으로만 사용 가능
    • 프로세스들은 각각 격리되어 있어서 상태를 공유하지 않음

 

 

Topic 36 칠판

  • 일종의 ‘자유방임주의’적 동시성
  • 칠판 접근 방법의 몇 가지 주요 특징
    • 칠판을 보며 새로운 정보를 얻고, 자기가 발견한 것을 칠판에 덧붙인다.
    • 사건을 해결하고 싶은 마음은 모두에게 있지만, 공통점은 그뿐이다.
    • 시간도 제각기 다를 수 있다.
    • 칠판에는 제한 없이 어떤 것이든 올릴 수 있다. 
  • 데이터의 도착 순서는 이제 상관없다. 어떤 사실이 칠판에 올라가면 적절한 규칙이 발동되도록 하면 된다.
    • 하지만 거기에는 비용이 따른다. 메시지 형식 및 API를 모아두는 중앙 저장소 를 운영하면 도움이 될 것이다.
    • 유용한 기법 : 특정한 비즈니스 작업 처리를 시작할 때 고유한 ‘추적 아이디trace id’를 만들어서 붙이기 (고유 식별자를 붙이면 사후 분석 용이)

 

" 의사 선생님, 이렇게 하면 아파요.
... 그러면 그렇게 하지 마세요. "

 


오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요

  • 결합은 나쁘다지만 시간적 결합을 아예 없앨 순 없다. 꼭 필요한 경우와 그 외의 경우가 있다. 그렇다보니 그 오묘한 경계에서 코드 한줄 순서가 바뀌면 애들이 살짝 맛이 가기 시작한다. 사고치기 전에 테스트에서 이런 버그를 잡아본적이 있어서 잡았다 요놈 지금은 나아졌다. multi-thread 환경에서만 개발을 하다보니 그 소소한 차이에 예민하지 않을 수 없더라. 아직 갈길이 멀지만서도 예전보단 실수가 많이 줄었을지도?
  • 액터의 예시에서 golang channel을 이용한 비동기 프로그램 방식이 생각났다. 단순히 정해진 타입의 신호(=메시지)만을 쳐다보며 깨어나서 contents에 따라 분기처리도 가능하다. 이를 좀더 응용해 callback 함수를 연결하여 큐처럼 사용하고 있다. 이런걸 액터라고 하는구나.
  • 칠판 토픽에서 고유 추적 아이디는 정말 유용하다는 것에 공감한다. 지금 내가 담당하는 서비스 모듈에서 하나의 task를 job이라고 명명해 job id를 유니크하게 관리하며 모든 작업의 단위로 통용하고 있는데, 문제가 생길때 이 job id만 알면 요청부터 어떤 응답이 언제 어떻게 나갔는지 알 수 있다. 물론 해당 내용에서 추천하는 칠판과 같은 솔루션을 이용하는건 아니지만 적절한 액터의 배치와 메인 db 운영으로도 충분한 경우가 많은 것 같다.

 


궁금한 내용이 있거나, 잘 이해되지 않는 내용이 있다면 적어보세요

  • 특별히 없다. 동시성. 멀티쓰레딩 등에 대한 실력이 점점 더 요구될 뿐...

댓글