동시성과 깔끔한 코드는 양립하기 어렵다.

동시성은 결합을 없애는 전략이다.
무엇과 언제를 분리하는 전략이다.

스레드가 하나인 프로그램은 무엇과 언제가 서로 밀접하다.
그래서 호출 스택을 살펴보면 프로그램 상태가 곧바로 드러난다.

흔히 단일 스레드 프로그램을 디버깅하는 프로그래머는 정지점을 정한 후 어느 정지점에 걸렸는지 살펴보면서 시스템 상태를 파악한다.

  • 동시성은 다소 부하를 유발한다. 성능 측면에서 부하가 걸리며, 코드도 더 짜야 한다.
  • 동시성은 복잡하다. 간단한 문제라도 동시성은 복잡하다.
  • 일반적으로 동시성 버그는 재현하기 어렵다. 그래서 진짜 결함으로 간주되지 않고 일회성 문제로 여겨 무시하기 쉽다.
  • 동시성을 구현하려면 흔히 근본적인 설계 전략을 재고해야 한다.

동시성 방어 원칙

단일 책임 원칙
SRP는 주어진 메서드/클래스/컴포넌트를 변경할 이유가 하나여야 한다.

  • 권장사항: 동시성 코드는 다른 코드와 분리하라.
    따름 정리: 자료 범위를 제한하라
    공유 객체를 사용하는 코드 내 임계영역을 보호하라.
  • 권장사항: 자료를 캡슐화하라. 공유 자료를 최대한 줄여라.
    따름 정리: 자료 사본을 사용하라
    공유 자료를 줄이려면 처음부터 공유하지 않는 방법이 제일 좋다.
    따름 정리: 스레드는 가능한 독립적으로 구현하라
    자신만의 세상에 존재하는 스레드를 구현한다.
    즉 다른 스레드와 자료를 공유하지 않는다.
  • 권장사항: 독자적인 스레드로, 가능하면 다른 프로세서에서,
    돌려도 괜찮도록 자료를 독립적인 단위로 분할하라.

라이브러리를 이해해라

권장사항: 언어가 제공하는 클래스를 검토하라.

실행 모델을 이해하라

  • 한정된 자원 : 다중 스레드 환경에서 사용하는 자원으로, 크기나 숫자가 제한적이다. 데이터 베이스 연결, 길이가 일정한 읽기/쓰기 버퍼 등이 예다.
  • 상호배제 : 한 번에 한 스레드만 공유 자료나 공유 자원을 사용할 수 있는 경우를 가리킨다.
  • 기아: 한 스레드나 여러 스레드가 굉장히 오랫동안 혹은 영원히 자원을 기다린다. 예를 들어, 항상 짧은 스레드에게 우선순위를 준다면, 짧은 스레드가 지속적으로 이어질 경우, 긴 스레드가 기아 상태에 빠진다.
  • 데드락: 여러 스레드가 서로가 끝나기를 기다린다. 모든 스레드가 각기 필요한 자원을 다른 스레드가 점유하는 바람에 어느 쪽도 더 이상 진행하지 못한다.
  • 라이브락 : 락을 거는 단계에서 각 스레드가 서로를 방해한다. 스레드는 계속해서 진행하려 하지만, 공명으로 인해, 굉장히 오랫동안 혹은 영원히 진행하지 못한다.

결론

다중 스레드 코드는 올바로 구현하기 어렵다.
간단했던 코드가 여러 스레드와 공유 자료를 추가하면서 악몽으로 변한다.
다중 스레드 코드를 작성한다면 각별히 깨끗하게 코드를 짜야 한다.

SRP를 준수한다.
POJO를 사용해 스레드를 아는 코드와 스레드를 모르는 코드를 분리한다.
스레드 코드를 테스트할때는 전적으로 스레드만 테스트한다.
즉, 스레드 코드는 최대한 집약되고 작아야 한다는 의미다.

profile
Front-End Developer

0개의 댓글