자바 다 중 스 레 드 동기 화 최적화 6 가지 방안

개술
프로세서 에 있 는 레지스터 의 읽 기와 쓰기 속 도 는 메모리 보다 몇 단계 빠르다.이러한 속도 모순 을 해결 하기 위해 서 그들 사이 에 고속 캐 시 를 넣 었 다.
캐 시 를 추가 하 는 것 은 캐 시 일치 성 이라는 새로운 문 제 를 가 져 왔 습 니 다.여러 개의 캐 시가 같은 메 인 메모리 영역 을 공유 하면 여러 개의 캐 시 데이터 가 일치 하지 않 을 수 있 으 므 로 이 문 제 를 해결 하기 위 한 프로 토 콜 이 필요 합 니 다.
자바 메모리 모델 에 서 는 주 메모리 와 스 레 드 작업 메모리 로 나 뉘 어 있 으 며,스 레 드 는 공유 데 이 터 를 사용 할 때 메 인 메모리 에서 작업 메모리 로 데 이 터 를 복사 하고,사용 이 끝 난 후에 메 인 메모리 에 기록 합 니 다.
자바 에서 다 중 스 레 드 가 동시에 발생 할 때 우 리 는 다 중 스 레 드 동기 화 방식 으로 메모리 의 일치 성 문 제 를 해결 할 수 있 습 니 다.일반적으로 우 리 는 프로그램 에 동기 화 자 물 쇠 를 추가 하여 데이터 의 안전 한 접근 을 보장 할 수 있 지만 동기 화 성능 문 제 를 자주 가 져 올 수 있다.그러면 본 장 은 흔히 볼 수 있 는 동기 화 문제 에 대해 최적화 방안 을 제시 할 것 이다.
읽 기와 쓰기 자물쇠
다 중 스 레 드 작업 에서 만약 우리 의 일부 데이터 가 자주 읽 히 지만,매우 적은 시기 에 기록 된다.이때 우리 가 synchronized 등 동기 화 방식 을 사용 하면 성능 이 매우 낮 을 것 이다.
이런 장면 에서 우 리 는 읽 기와 쓰기 자 물 쇠 를 사용 하여 최적화 해 야 한다.
읽 기와 쓰기 자물쇠 의 특징:
읽 기와 쓰기 자 물 쇠 는 한 쌍 의 자물쇠,읽 기와 쓰기 자 물 쇠 를 유지 합 니 다4.567917.공유 읽 을 수 있 지만 한 개 만 쓸 수 있 습 니 다읽 기와 쓰 기 는 서로 배척 하지 않 고 읽 기와 쓰 기 는 서로 배척 하 며 쓰 기 는 서로 반박한다어떤 특정한 장면 에 서 는 읽 기와 쓰기 자 물 쇠 를 사용 하면 다 중 스 레 드 병행 작업 의 효율 을 크게 향상 시 킬 수 있다.읽 기와 쓰기 자물쇠 에서 읽 기 자 물 쇠 는 자물쇠 가 아니 기 때문에 동시에 실행 할 수 있 고 읽 기 효율 을 현저히 높 일 수 있 습 니 다.자 물 쇠 를 쓸 때 만 자 물 쇠 를 배열 합 니 다.이 때 는 자 물 쇠 를 쓸 때 까지 기 다 려 야 합 니 다.
ReetrantReadWriteLock
ReadWriteLock 인터페이스
자바 와 가방 에서 ReadWrite Lock 은 인터페이스 로 읽 기와 쓰기 잠 금 방법 을 추상 화 했다.

public interface ReadWriteLock {
    /**
     * Returns the lock used for reading.
     *
     * @return the lock used for reading
     */
    Lock readLock();

    /**
     * Returns the lock used for writing.
     *
     * @return the lock used for writing
     */
    Lock writeLock();
}

ReadWriteLock 은 하나의 자 물 쇠 를 관리 합 니 다.하 나 는 읽 기 전용 자물쇠 이 고 하 나 는 쓰기 자물쇠 입 니 다.
Reetrant ReadWriteLock 클래스
자바 병렬 라 이브 러 리 에서 Reetrant ReadWriteLock 은 ReadWriteLock 인 터 페 이 스 를 실현 하고 다시 들 어 갈 수 있 는 기능 을 추가 합 니 다.
1.Reetrant ReadWriteLock 잠 금 획득 순 서 는 두 가지 모드 가 있 습 니 다.
4.567917.불공 정 모드(기본 값):불공 정 자 물 쇠 는 경쟁 획득 을 주장 하고 하나 이상 의 읽 기 또는 쓰기 스 레 드 를 늦 출 수 있 지만 공평 자물쇠 보다 더 높 은 스루풋 을 가 질 수 있 습 니 다4.567917.공평 모드:공평 모드 로 초기 화 될 때 스 레 드 는 대열 의 순서 로 자 물 쇠 를 가 져 옵 니 다.
2.재 접속 가능
Reetrant ReadWriteLock 자 물 쇠 는 다시 들 어 갈 수 있 습 니 다.물론 하나의 스 레 드 가 자 물 쇠 를 몇 번 가 져 오 면 몇 번 의 자 물 쇠 를 풀 어야 합 니까?
4.567917.읽 기 스 레 드 에서 읽 기 자 물 쇠 를 가 져 온 후에 다시 읽 기 자 물 쇠 를 가 져 올 수 있 습 니 다4.567917.스 레 드 를 써 서 자 물 쇠 를 가 져 온 후에 다시 자 물 쇠 를 가 져 올 수 있 고 읽 기 자 물 쇠 를 가 져 올 수 있 습 니 다.
3.잠 금 강등
읽 기와 쓰기 자물쇠 에서 잠 금 강등:쓰기 자물쇠 에서 읽 기 자물쇠 로 바 뀌 기;자물쇠 업그레이드:읽 기 자물쇠 에서 쓰기 자물쇠 로.
  • ReentrantReadWriteLock 은 자물쇠 업 그 레이 드 를 지원 하지 않 습 니 다.즉,하나의 스 레 드 가 읽 기 자 물 쇠 를 가지 고 있 을 때 이 스 레 드 가 다시 쓰기 자 물 쇠 를 사용 할 때 안 됩 니 다.만약 한 라인 이 읽 기 자 물 쇠 를 가지 고 있다 면,쓰기 자 물 쇠 를 가 져 오기 전에 반드시 읽 기 자 물 쇠 를 풀 어야 한다
  • ReentrantReadWriteLock 은 잠 금 강 하 를 지원 합 니 다.즉,현재 스 레 드 가 잠 금 을 쓰 는 소유자 이 고 잠 금 을 쓰 는 상 태 를 유지 하 는 동시에 읽 기 자 물 쇠 를 얻 은 다음 에 잠 금 을 쓰 는 과정 입 니 다.자 물 쇠 를 가 져 오고 읽 기 자 물 쇠 를 가 져 오 며 자 물 쇠 를 풀 어 주 는 순서 에 따라 자 물 쇠 를 읽 기 자물쇠 로 강등 시 킬 수 있 습 니 다
  • 읽 기 및 쓰기 잠 금 상태의 디자인
    읽 기와 쓰기 자물쇠 의 상 태 는 int 값 으로 표 시 됩 니 다.state(int 32 비트)필드 는 높 은 16 비트 와 낮은 16 비트 로 나 뉘 는데 그 중에서 높 은 16 비트 는 읽 기 잠 금 개 수 를 나타 내 고 낮은 16 비트 는 잠 금 개 수 를 나타 낸다.
    예 를 들 어 현재 한 스 레 드 는 자 물 쇠 를 가 져 왔 고 두 번 다시 들 어 갔 기 때문에 16 비트 가 3 이 낮 고 이 스 레 드 는 읽 기 자 물 쇠 를 가 져 왔 으 며 한 번 더 들 어 갔 기 때문에 높이 16 비트 는 2 이다.자 물 쇠 를 가 져 올 때 자 물 쇠 를 0 으로 읽 지 않 으 면 자 물 쇠 를 가 져 오 는 이 스 레 드 일 것 이다.
    쓰기 시 복사
    쓰기 시 복사(Copy-on-write,COW 로 약칭)는 컴퓨터 프로 그래 밍 분야 의 최적화 전략 이다.그 핵심 사상 은 여러 호출 자가 같은 자원 을 동시에 요구 하면 같은 지침 이 같은 자원 을 가리 키 는 것 이다.특정한 호출 자가 자원 의 내용 을 수정 하려 고 할 때 까지 시스템 은 이 호출 자 에 게 전용 사본 을 복사 하고 다른 호출 자가 본 최초의 자원 은 변 하지 않 는 다 는 것 이다.이 과정 은 다른 호출 자 들 에 게 투명 하 다.이 방법 은 호출 자가 이 자원 을 수정 하지 않 으 면 복사 본 이 생 성 되 지 않 는 다 는 것 이 주요 장점 입 니 다.따라서 여러 호출 자 는 작업 을 읽 을 때 같은 자원 을 공유 할 수 있 습 니 다.
    자바 에서 Copy on Write 라 는 메커니즘 은 보통 집합 에 사용 되 며,동시 방문 하 는 경우 JAVA 의 Containers 요 소 를 수정 해 야 할 때 이 용 기 를 직접 수정 하지 않 고 사본 을 복사 해 사본 에서 수정 합 니 다.수정 이 완료 되면 원래 용기 의 인용 을 가리 키 는 새로운 용기(던 전 용기)입 니 다.
    쓰기 시 복사 하 는 특징
    4.567917.원본 용 기 를 수정 하지 않 기 때문에 사본 용기 만 수정 합 니 다.따라서 원시 용 기 를 병발 적 으로 읽 을 수 있다.그 다음으로 읽 기 작업 과 쓰기 작업 의 분 리 를 실현 하고 읽 기 작업 은 원시 용기 에서 발생 하 며 쓰기 작업 은 사본 용기 에서 발생 한다4.567917.데이터 일치 성 문제:수정 작업 이 사본 에서 발생 하기 때문에 읽 기 작업 의 스 레 드 는 새로 수 정 된 데이터 내용 을 즉시 읽 지 못 할 수 있 지만 최종 수정 작업 은 용 기 를 완성 하고 업데이트 하기 때문에 이것 은 최종 일치 성 입 니 다4
  • CopyonWrite 용 기 는 많이 읽 고 적 게 쓰 는 장면 에 적용 된다.쓰기 작업 을 할 때 용 기 를 복사 해 야 합 니 다.메모리 비용 이 많이 듭 니 다
  • 데이터 의 강 한 일치 성에 적합 하지 않다.데이터 수정 을 요구 한 후 바로 읽 을 수 있 으 면 쓰기 시 복사 기술 을 사용 할 수 없다.최종 일치 성 이기 때문이다자바 작성 시 용기 클래스 복사
    JDK 에 서 는 CopyOnWriteArrayList 클래스 와 CopyOnWriteArraySet 클래스 를 제공 하여 쓰기 시 복 제 를 실현 합 니 다.
    자물쇠 의 입 도 를 줄이다.
    만약 에 우리 가 큰 데이터 조작 류 에서 자 물 쇠 를 대량으로 사 용 했 고 같은 자 물 쇠 를 사용 했다 면 이때 우리 의 다 중 스 레 드 동기 화 효율 은 매우 낮 아 질 것 이다.
    우 리 는 데 이 터 를 서로 다른 유형 과 응용 장면 에 따라 분할 한 다음 에 서로 다른 자물쇠 로 동기 화 할 수 있다.그러면 서로 다른 장면 에서 자물쇠 의 충돌 문제 가 발생 하지 않 고 동기 화 효율 을 크게 향상 시 킬 수 있다.
    이 방안 은 쉽게 말 하면 하나의 큰 자 물 쇠 를 여러 개의 작은 자물쇠 로 나 누 면 다 중 스 레 드 병행 집행 의 효율 을 현저히 높 일 수 있다.
    자물쇠 의 점유 시간 을 줄이다.
    만약 에 비교적 큰 방법 에서 우 리 는 이 방법 에 자 물 쇠 를 직접 추가 했다.그러나 우리 가 동기 화 해 야 할 곳 은 이 방법 중의 한 줄 의 조작 코드 일 뿐이다.그러면 아주 나 쁜 동기 화 사용 방식 이다.
    우 리 는 전체 함수 가 자 물 쇠 를 추가 하 는 것 이 아니 라 자 물 쇠 를 사용 하 는 코드 줄 에 세분 화 할 수 있 습 니 다.그러면 자물쇠 의 보유 시간 이 적어 지고 다 중 스 레 드 동기 화 성능 을 향상 시 킬 수 있 습 니 다.
    이 방안 은 동기 블록 의 코드 범 위 를 줄 여 자물쇠 의 보유 시간 을 낮 추고 다 중 스 레 드 동기 화 성능 을 최적화 하 는 목적 을 달성 하 는 것 이다.
    자물쇠 조 화
    자물쇠 의 점유 시간 을 줄 이면 성능 을 높 일 수 있다 고 하지만 이런 방식 은 적용 되 지 않 을 때 도 있다.
    예 를 들 어 하나의 순환 에서 우 리 는 순환 체 에서 자 물 쇠 를 사용 하면 오히려 성능 을 떨 어 뜨 릴 수 있다.이때 우 리 는 순환 이 시작 되 기 전에 자 물 쇠 를 넣 고 끝 난 후에 풀 어야 한다.즉,자 물 쇠 를 굵게 하 는 것 이다.
    왜 그 럴 까요?
    잠 금 요청,방출,상태 수정 등 을 빈번하게 하면 시스템 자원 이 많이 소모 되 고 성능 이 떨 어 지기 때문이다.
    ThreadLocal
    동기 화 효율 이 낮은 것 은 다 중 스 레 드 동기 화 대기 로 인해 발생 한 것 이다.그러면 우 리 는 생각 을 바 꿀 수 있다.만약 에 모든 스 레 드 가 데 이 터 를 가지 게 한다 면 경쟁 문제 가 존재 하지 않 고 동기 화 잠 금 도 필요 없다.이렇게 하면 다 중 스 레 드 병발 의 성능 을 어느 정도 향상 시 킬 것 이다.
    ThreadLocal 관련 실현 원리 및 사용 에 대해 서 는 이전 글 인 을 참고 할 수 있 습 니 다.
    총결산
    자바 에서 잠 금 을 사용 하여 다 중 스 레 드 의 동기 화 문 제 를 해결 하고 데이터 의 일치 성 을 보장 할 수 있 으 나 많은 문 제 를 대리 할 수 있 습 니 다.본 장 은 다 중 스 레 드 동기 화의 몇 가지 최적화 방안 을 정리 하 였 습 니 다.
    4.567917.특정한 장면(대부분 많이 읽 고 적 게 쓰 는 장면)은 읽 기와 쓰기 자 물 쇠 를 사용 하면 다 중 스 레 드 병행 작업 의 효율 을 크게 향상 시 킬 수 있다.읽 기와 쓰기 자물쇠 에서 읽 기 자 물 쇠 는 자물쇠 가 아니 기 때문에 동시에 실행 할 수 있 고 읽 기 효율 을 현저히 높 일 수 있 습 니 다.자 물 쇠 를 쓸 때 만 자 물 쇠 를 배열 합 니 다.이 때 는 자 물 쇠 를 쓸 때 까지 기 다 려 야 합 니 다
  • 자바 병렬 라 이브 러 리 에서 Reetrant ReadWriteLock 은 ReadWriteLock 인 터 페 이 스 를 실현 하고 재 입 가능 한 기능 을 추가 합 니 다
  • 4.567917.작성 시 복제 메커니즘 은 동시 다발 효율 을 현저히 높 일 수 있 으 며,동시 다발 적 으로 방문 하 는 상황 에서 JAVA 에서 Containers 의 요 소 를 수정 해 야 할 때 이 용 기 를 직접 수정 하지 않 고 먼저 사본 을 복사 하여 사본 에서 수정 할 수 있다.수정 이 완료 되면 원래 용기 의 인용 을 가리 키 는 새로운 용기(던 전 용기)입 니 다.CopyonWrite 용 기 는 많이 읽 고 적 게 쓰 는 장면 에 적용 된다.쓰기 작업 을 할 때 용 기 를 복사 해 야 합 니 다.메모리 비용 이 많이 듭 니 다4.567917.자물쇠 의 입 도 를 줄 여 동기 효율 을 높 인 다4.567917.자물쇠 의 점유 시간 을 줄 이 는 것 은 동기 블록 의 코드 범 위 를 줄 여 자물쇠 의 보유 시간 을 낮 추고 다 중 스 레 드 동기 화 성능 을 최적화 하 는 목적 을 달성 하 는 것 을 말한다4.567917.가끔 은 대량의 자물쇠 와 자물쇠 상태 수정 이 시스템 자원 의 소 모 를 초래 할 수 있 기 때문에 우 리 는 자물쇠 의 조 화 를 통 해 성능 을 최적화 할 수 있다4.567917.우 리 는 생각 을 바 꾸 고 ThreadLocal 을 사용 하여 다 중 스 레 드 병행 의 성능 을 향상 시 킬 수 있다자바 다 중 스 레 드 의 동기 화 최적화 에 관 한 6 가지 방안 에 관 한 글 은 여기까지 소개 되 었 습 니 다.더 많은 자바 다 중 스 레 드 동기 화 최적화 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 우 리 를 많이 지지 해 주세요!

    좋은 웹페이지 즐겨찾기