자료 범위를 제한: 공유 자원에 접근할 때는 동기적으로 접근하도록 하여 여러 스레드가 동시에 하나의 자원을 접근하는 것을 방지해라
대표적인 방법: 캡슐화를 통해 자원의 직접 접근을 방지
자료를 복제해 사본을 만들어 전달: 읽기 전용 객체를 만들어 공유 객체를 피하는 방법
가능한 독립적인 기능을 가진 스레드: 외부의 자료 공유없이 오직 스레드 자신이 가지고 있는 자료로 기능이 구현되어야 함
자료구조를 사용해야 한다면 thread-safe한 자료구조를 사용해라(java.util.concurrent)
다중 스레드를 사용하는 대표적인 모델
Producer-Consumer
Producer: 데이터를 버퍼나 큐를 통해 전달
Consumer: 데이터를 받아서 처리
Producer가 데이터를 보내면 Consumer에게 signal을 보내 데이터를 가져가라고 신호를 보내고 Consumer가 데이터를 가져가서 처리
주의: Producer가 먼저 죽거나 Consumer 가 signal을 받는데 실패한다면 deadlock이 발생
Readers-Writers
Reader: 공유 자원을 읽는 스레드
Writer: 공유 자원을 업데이트하는 스레드
여러개의 reader와 writer가 존재해 공유 자원을 사용
주의: reader, writer 중에 한 곳이라도 공유 자원의 점유율이 높아지면 다른 쪽이 공유 자원을 사용하지 못하는 starvation문제가 발생
Dining Philosophers
deadlock 상태를 설명하는 문제
여러명의 철학자들이 원형 탁자 테이블에서 식사를 진행할려는 상황이고 포크가 왼쪽에 있으며 양쪽 포크를 모두 집어야 식사가 가능한 상태일 때 모든 철학자들이 왼쪽에 있는 포크를 집으면 오른쪽에 있는 포크를 집기 위해 대기를 해서 철학자 모두가 식사를 하지 못하는 문제
스레드 코드 테스트
스레드를 고려하기 전에 순차적으로 잘 돌아가는 코드를 먼저 만들어라
시스템의 실패는 일회성이라고 넘어가서는 안된다
말이 안되는 실패는 스레드 문제일 수 있다
스레드는 독립적으로 실행 가능할 정도로 구현해라
다른 플랫폼에서 스레드 테스트 코드를 돌려봐라
OS마다 스레드 처리 정책이 달라 같은 코드라도 OS에 따라 실패할 수 있다
코드에 보조코드를 넣어 스레드 흐름을 강제로 흔들어서 실패를 발생시켜봐라
스레드가 실행될 때마다 매번 다르게 실행되어서 오류를 최대한 많이 찾을려 해라
생각
스레드 테스트를 하면서 FIRST원칙을 어떻게 지킬 수 있을까를 고민한 적이 있다. 당시에는 '스레드로 발생할 수 있는 모든 경우의 수를 체크할 수 없다' 라고 잠정 결론을 짓고 순차적인 코드로만 테스트를 했었다. 이 챕터에서 제시한 스레드 환경에서의 테스트는 '개발자가 모든 경우의 수를 예측할 수 없기에 오류를 최대한 많이 찾아낼 수 있는 환경으로 접근하라'는 방식으로 이해하였다. 스레드의 테스트는 언젠가 실패할 수 있다는 것을 감안하고 작성할 수 밖에 없구나라는 생각을 하였다.
복수의 공유 자원을 독점해야 작업을 진행할 수 있을때 모든 스레드가 부분적으로만 독점해서 데드락이 발생하는 문제
스레드 테스트하기
이해할 수 없는 문제는 잠정적으로 스레드 문제로 간주하라
다중 스레드와 관련 없는 부분부터 테스트하라
다양한 환경(속도 등)에서 다중 스레드를 테스트하라
상황에 맞게 다중 스레드를 조율할 수 있게 테스트하라
프로세서 수보다 많은 스레드를 테스트하라
다른 플랫폼에서 돌려보라
강제로 실패를 일으켜라
생각
다중 스레드 코드는 거의 사용한 적이 없지만, 이 장에서 다루는 데드락 문제 등은 이론적으로나마 접한 적이 있다. 다중 스레드 환경에 대해 다양한 테스트 원칙을 제시한 것으로부터 저자가 테스트 코드를 상당히 중시한다는 인상을 다시 느꼈으며, 각각의 테스트 원칙에 대한 문단에서 스레드 환경에서 발생할 수 있는 문제에 대한 깊은 생각이 느껴진다.
요약
동시성은 무엇과 언제라는 결합을 없애는 전략이다
동시성 방어 원칙
SRP 준수: 동시성으로만 처리할 수 있는 책임만 분리해서 스레드로 만들어라
자료 범위를 제한: 공유 자원에 접근할 때는 동기적으로 접근하도록 하여 여러 스레드가 동시에 하나의 자원을 접근하는 것을 방지해라
자료를 복제해 사본을 만들어 전달: 읽기 전용 객체를 만들어 공유 객체를 피하는 방법
자료구조를 사용해야 한다면 thread-safe한 자료구조를 사용해라(java.util.concurrent)
다중 스레드를 사용하는 대표적인 모델
Producer-Consumer
Readers-Writers
Dining Philosophers
스레드 코드 테스트
스레드를 고려하기 전에 순차적으로 잘 돌아가는 코드를 먼저 만들어라
시스템의 실패는 일회성이라고 넘어가서는 안된다
말이 안되는 실패는 스레드 문제일 수 있다
스레드는 독립적으로 실행 가능할 정도로 구현해라
다른 플랫폼에서 스레드 테스트 코드를 돌려봐라
코드에 보조코드를 넣어 스레드 흐름을 강제로 흔들어서 실패를 발생시켜봐라
생각
스레드 테스트를 하면서 FIRST원칙을 어떻게 지킬 수 있을까를 고민한 적이 있다. 당시에는 '스레드로 발생할 수 있는 모든 경우의 수를 체크할 수 없다' 라고 잠정 결론을 짓고 순차적인 코드로만 테스트를 했었다. 이 챕터에서 제시한 스레드 환경에서의 테스트는 '개발자가 모든 경우의 수를 예측할 수 없기에 오류를 최대한 많이 찾아낼 수 있는 환경으로 접근하라'는 방식으로 이해하였다. 스레드의 테스트는 언젠가 실패할 수 있다는 것을 감안하고 작성할 수 밖에 없구나라는 생각을 하였다.