Book Record/Clean Code

[Clean Code] 13장 동시성(1)

lakelight 2022. 11. 29. 19:08
728x90
반응형
깨끗한 코드를 작성하기 위한 열세번째 기록

 

동시성이 필요한 이유

동시성은 결합을 없애는 전략입니다. 즉, 무엇과 언제를 분리하는 전략입니다. 무엇과 언제를 분리하면 애플리케이션 구조와 효율이 극적으로 나아집니다.

예시1) 서블릿 모델을 살펴보면 웹 혹은 EJB 컨테이너라는 우산 아래서 돌아가는데 컨테이너 들은 동시성을 부분적으로 관리합니다. 웹 요청이 들어올 때 마다 웹 서버는 비동기식으로 서블릿을 실행합니다. 그래서 서블릿 프로그래머는 들어오는 모든 웹 요청을 관리하지 않습니다. 

예시2) 매일 수많은 웹 사이트에서 정보를 가져와 요약하는 정보 수집기를 봤을 때 단일 스레드 프로그램이라면, 수집하는데 많은 시간이 소요될 것입니다. 단일 스레드 수집기웹 소켓에서 입출력기다리는 시간이 아주 많기 때문입니다. 이 때 다중 스레드 알고리즘을 이용한다면 성능을 높일 수 있습니다.

 

동시성에 미신과 오해

1. 동시성은 항상 성능을 높여주는 것이 아닙니다. 여러 프로세서가 동시에 처리할 독립적인 계산이 충분히 많은 경우에만 성능을 높여 줍니다.

2. 다중 스레드 시스템을 사용하면 무엇과 언제를 분리하는 일이기 때문에 시스템 구조가 크게 달라집니다.

3. 컨테이너가 어떻게 동작하고, 어떻게 동시 수정이 가능하며, 데드락 등과 같은 문제를 피할 수 있는지를 알아야만 합니다.

 

난관

하나의 공유 자원이 있고, 하나의 메서드를 통해 공유자원에 두 쓰레드가 접근 했을 때 동시에 접근을 해서 값이 올바르지 않게 나오는 경우가 있습니다.

 

난관(동시성)을 방어하는 원칙

1. 단일 책임 원칙

동시성 코드는 복잡하기 때문에 다른 코드와 분리해야 한다는 의미입니다. 

 

2. 자료 범위를 제한하라

난관과 같이 공유 자원을 수정하던 두 스레드가 서로 간섭하여 예상치 못한 결과를 내놓을 수 있기 때문에 공유 객체를 사용하는 임계 영역synchronized 키워드를 통해 보호해야 합니다. 임계 영역을 보호하는 부분은 빼먹을 수 있기 때문에 올바르게 보호했는지 확인해야 합니다.
자료를 캡슐화 하고, 공유 자원을 최대한 줄여야 합니다.

 

3. 자료 사본을 사용하라

공유 자원을 복사해서 읽기 전용으로 사용하는 방법이 있습니다. 또한 각 스레드가 객체를 복사해 사용한 후 한 스레드가 해당 사본에서 결과를 가져오는 방법도 가능합니다.


4. 스레드는 가능한 독립적으로 구현하라

다른 스레드와 자료를 공유하지 않도록 구현합니다. 각 스레드는 클라이언트 요청 하나를 처리합니다. 그리고 모든 정보는 비공유 출처에서 가져오며 로컬 변수에 저장합니다. 그러면 다른 스레드와 동기화 할 필요가 없어집니다.
독립적인 스레드로, 가능하면 다른 프로세서에서, 돌려도 괜찮도록 자료독립적인 단위로 분활해야 합니다.

 

라이브러리를 이해하라

ConcurrentHashMap

다중 스레드 환경에서 사용해도 안전하며, 성능도 좋은 Map 클래스, 거의 모든 상황에서 HashMap보다 빠르다고 합니다. 또한 동시 읽기/쓰기를 지원하며, 자주 사용하는 복합 연산다중 스레드 상에서 안전하게 만든 메서드로 제공합니다.

 

ReentrantLock

한 메서드에서 잠그고 다른 메서드에서 푸는 락입니다.

 

Semaphore

전형적인 세마포입니다. 개수가 있는 락입니다.

 

CountDownLatch

지정한 수 만큼 이벤트가 발생하고 나서야 대기 중인 스레드를 모두 해제하여 모든 스레드에게 동시에 공평하게 시작할 기회를 주는 락입니다.

 

기본 용어를 이해하라.

한정된 자원(Bound Resource)

다중 스레드 환경에서 사용하는 자원으로, 크기나 숫자가 제한적입니다. 데이터베이스 연결, 길이가 일정한 읽기/쓰기 버퍼 등이 예입니다.

 

상호 배제(Mutual Exclusion)

한 번에 한 스레드만 공유 자료나 공유 자원을 사용할 수 있는 경우를 가리킵니다.

 

기아(Starvation)

한 스레드여러 스레드가 굉장히 오랫동안 혹은 영원히 자원을 기다리는 상태를 말합니다. 예를 들어, 항상 짧은 스레드에게 우선순위를 준다면, 짧은 스레드가 지속적으로 이어질 경우, 긴 스레드는 기아 상태가 된다고 표현합니다.

 

데드락(Deadlock)

여러 스레드가 서로 끝나기를 기다리는 상태를 말합니다. 모든 스레드가 각기 필요한 자원을 다른 스레드가 점유하는 바람에 어느 쪽도 더 이상 진행하지 못하는 현상을 말합니다. (무한 loop)

 

라이브락(Livelock)

락을 거는 단계에서 각 스레드가 서로를 방해하는 상태입니다. 스레드는 계속해서 진행하려 하지만, 공명으로 인해 굉장히 오랫동안 혹은 영원히 진행하지 못하는 상태를 말합니다.

 

 

 

마무리

동시성은 항상 어렵다고 생각하는 개념입니다. 책을 통해 개념정리도 하고
깨끗한 코드를 작성하는 동시에 동시성 문제도 잡을 수 있는 전략을 알 수 있어서
앞으로 저에게 많은 도움이 될 것 같습니다.

포스팅 읽어주셔서 감사합니다.

 

 

[출처]
Clean Code (클린 코드,애자일 소프트웨어 장인 정신), 로버트 C. 마틴 저

728x90
반응형

'Book Record > Clean Code' 카테고리의 다른 글

[Clean Code] 13장 동시성(2)  (2) 2022.12.04
[Clean Code] 12장 창발성  (2) 2022.11.25
[Clean Code] 11장 시스템  (2) 2022.11.19
[Clean Code] 10장 클래스  (0) 2022.11.06
[Clean Code] 9장 단위 테스트  (2) 2022.10.24