11-27-클린코드¶
클린코드 p408-p446
웹소켓 예제¶
- I/O - 소켓 사용, 데이터베이스 연결, 가상 메모리 스와핑 기다리기 등
- 프로세서 - 수치 계산, 정규 표현식 처리, 가비지 컬렉션 등
- 프로그램이 프로세서 연산에 시간이 걸린다면? 새로운 하드웨어를 추가하여 성능을 높인다.
- CPU 사이클은 한계가 있기 때문에 스레드를 늘리는 건 해결책이 아님
- I/O 연산에 시간에 시간을 보낸다면? 동시성이 성능을 높여줄 수 있음 -> 한쪽이 I/O를 기다리는 동안 다른 쪽이 CPU 활용
- 스레드를 관리하는 코드는 스레드만 관리
- 동시성 문제는 그 자체만으로도 추적하기 어렵다 -> 관리 전략이 변할 때 전체 코드에 미치는 영향이 작아지며 다른 책임을 간섭하지 않음
- 다중 스레드 프로그램에서는 단일 책임 원칙이 중요
synchronized¶
- 반환값은 lastIdUsed 값과 동일하다. 두 값 모두 메서드를 호출하기 전보다 1이 크다.- 어떤 스레드가 메서드를 실행하면 Intrinsic Lock 획득 -> 한번에 하나의 스레드만 -2개의 스레드가 동시에 incrementValue()를 호출한다면?
++lastIdUsed 코드 구역이 임계구역
- 해당 작업이 완료되거나 예외가 발생하면 lock이 해제
- 대기하던 다른 스레드가 메서드 실행
- synchronized 키워드는 단계를 원자적 작업으로 묶어주어 다른 스레드가 끼어들지 못하게 강제
알아야 할 것
- 공유 객체/값이 있는 곳
- 동시 읽기/수정 문제를 일으킬 소지가 있는 코드
- 동시성 문제를 방지하는 방법
다중 스레드 환경에서 안전하지 않은 클래스¶
- SimpleDateFormat
- 데이터베이스 연결
- java.util 컨테이너 클래스
- java.util.concurrent: 스레드에 안전한 집합 클래스 제공
- 서블릿
메서드 사이에 존재하는 의존성¶
- 서버 기반 잠금
- 코드 중복이 줄어들고 성능이 좋아진다.
- 오류 발생가능성 감소
- 스레드 정책이 서버 하나로 구현
- ADAPTER 패턴으로 API 변경 후 잠금 추가
- 스레드에 안전하며 인터페이스가 확장된 집합 클래스 사용
- 동기화 영역은 작을수록 좋다
데드락¶
- 상호 배제 Mutual exclusion
- 공유하는 자원을 여러 스레드가 동시에 사용하지 못하며 개수가 제한
- 데이터베이스 연결, 쓰기용 파일 열기, 레코드 락, 세마포어 등
- 잠금 & 대기 Lock & Wait
- 스레드가 자원을 점유하면 작업을 마칠 때까지 필요한 나머지 자원까지 점유
- 선점 불가 No preemption
- 한 스레드가 다른 스레드로부터 자원을 빼앗지 못함
- 순환 대기 Circular wait
- 순환 구조로 서로서로 필요한 자원을 점유
데드락 피하기 전략¶
- 상호 배제 조건 깨기
- 동시에 사용해도 괜찮은 자원 사용
- 스레드 수 이상으로 자원 수 사용
- 자원을 점유하기 전 필요한 자원 확인
- 잠금 & 대기 조건 깨기
- 각 자원을 점유하기 전 확인하여 하나라도 점유하지 못하면 모든 자원을 내놓고 다시 시작
- 기아 Starvation: 한 스레드가 계속해서 필요한 자원 점유를 못함
- 라이브락 Livelock: 여러 스레드가 동시에 진입하면 모든 자원을 점유하지 못하고 다시 시작 반복
- 선점 불가 조건
- 다른 스레드로부터 자원을 뺏어오는 방법
- 순환 대기 조건 깨기
- 모든 스레드가 일정 순서에 동의하고 그 순서로만 자원을 할당
- 자원 할당 순서와 사용 순서가 상이하여 자원을 필요 이상으로 점유
- 순서에 따라 자원 할당하기가 어려움
다중 스레드 코드 테스트¶
- nextId의 현재 값을 기억한다. - 스레드 두 개를 생성한다. 각 스레드가 takeNextId()를 한 번씩 호출한다. - nextId가 처음보다 2 증가했는지 확인한다. - nextId가 2 대신에 1만 증가할 때까지 위 단계를 반복한다.에필로그¶
Test Obsessed!