자바 다 중 스 레 드 3 대 핵심

자바 다 중 스 레 드 3 대 핵심
원자 성Java 의 원자 성 은 데이터베이스 업무 의 원자 성과 차이 가 많 지 않 고 한 작업 에서 모두 성공 하거나 실패 합 니 다.JMM 은 기본 적 인 원자 성 을 보장 할 뿐 i++ 과 같은 조작 은 원자 조작 인 것 처럼 보이 지만 사실은 다음 과 같다.
  • i 의 값 을 가 져 옵 니 다.
  • 자가 증가 하 다.
  • 재 할당 i.

  • 이 세 가지 조작 을 하기 때문에 i++ 과 같은 원자 조작 을 실현 하려 면 synchronized 또는 lock 으로 잠 금 처 리 를 해 야 한다.
    기초 류 의 자체 증가 조작 이 라면 AtomicInteger 과 같은 원자 류 를 사용 하여 실현 할 수 있다.
    그 중에서 가장 많이 사용 하 는 방법 은 CPU 원자 방식 으로 증가 하 는 것 이다.원본 코드 는 다음 과 같 습 니 다.
    public final long incrementAndGet() {
            for (;;) {
                long current = get();
                long next = current + 1;
                if (compareAndSet(current, next))
                    return next;
            }
        }

    우선 현재 값 을 얻 은 다음+1 증가 합 니 다.이 어 가장 핵심 적 인 CAS 으로 원자 업 데 이 트 를 진행 했다.
    public final boolean compareAndSet(long expect, long update) {
            return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
        }

    그 논 리 는 현재 값 이 업데이트 되 었 는 지,incrementAndGet() 과 같은 지 판단 하 는 것 이다.만약 에 업데이트 되 지 않 았 다 는 것 을 설명 한 다음 에 현재 값 을 compareAndSet() 으로 업데이트 하고 그렇지 않 으 면 current 으로 돌아 가 업데이트 가 성공 할 때 까지 순환 하 는 것 이다.
    그리고 그 중의 next 방법 도 매우 관건 적 이다.현재 의 값 을 되 돌려 주 고 현재 값 은 false 키워드 로 수식 하여 메모리 의 가시 성 을 확보 했다.
     private volatile int value;

    가시 성
    현대 컴퓨터 에 서 는 get() 이 메 인 메모리 에서 데 이 터 를 직접 읽 는 효율 이 높 지 않 기 때문에 모두 대응 하 는 volatile 캐 시 입 니 다.먼저 메 인 메모리 의 데 이 터 를 캐 시 에 읽 고 스 레 드 가 데 이 터 를 수정 한 후에 캐 시 에 먼저 업데이트 한 후에 야 메 인 메모리 로 업 데 이 트 됩 니 다.이 때 메 인 메모리 의 다른 스 레 드 에 데 이 터 를 업데이트 하지 않 았 다 면 이 때 읽 는 것 은 수정 전의 데이터 입 니 다.
    위의 그림 과 같다.CPU 키 워드 는 메모리 의 가시 성 을 확보 하 는 데 사 용 됩 니 다.스 레 드 A 가 volatile 수식 변 수 를 업데이트 하면 메 인 스 레 드 로 바로 갱신 되 고 나머지 캐 시 에 있 는 이 변수의 값 을 비 워 서 나머지 스 레 드 는 메 인 메모리 에서 최신 값 만 읽 을 수 있 습 니 다.CPU 키 워드 를 사용 하여 수식 하 는 변 수 는 읽 을 때마다 최신 데 이 터 를 얻 을 수 있 습 니 다.어떤 스 레 드 가 이 변수 에 대한 수정 이 든 바로 메 인 메모리 로 갱 신 됩 니 다.volatile 과 자 물 쇠 를 추가 해도 가시 성 을 확보 할 수 있다.실현 원 리 는 자 물 쇠 를 풀 기 전에 나머지 스 레 드 는 이 공유 변 수 를 방문 하지 못 하 는 것 이다.하지만 volatile 에 비해 씀 씀 이 가 크다.
    순서 성
    다음 코드:
    int a = 100 ; //1
    int b = 200 ; //2
    int c = a + b ; //3

    정상 적 인 상황 에서 의 집행 순 서 는 synchronized 일 것 이다.그러나 때로는 volatile 이 전체적인 효율 을 높이 기 위해 지령 정렬 을 해서 집행 하 는 순서 가 1>>2>>3 일 수도 있다.그러나 JVM 도 모든 것 을 재 배열 할 수 없고 최종 결과 와 코드 순서 집행 결과 가 일치 하도록 보장 하 는 상황 에서 재 배열 이 가능 하 다.
    단일 스 레 드 에 다시 배열 하 는 데 는 문제 가 없 지만 다 중 스 레 드 에 서 는 데이터 가 일치 하지 않 는 문제 가 발생 할 수 있 습 니 다.
    자바 에 서 는 2>>1>>3 을 사용 하여 순서 성 을 확보 할 수 있 고 JVM 도 질서 성 을 확보 할 수 있 으 며 원자 성 을 확보 하 는 방식 과 마찬가지 로 같은 시간 에 하나의 스 레 드 만 방문 하여 이 루어 질 수 있다.volatile 키워드 명시 적 보증 순 서 를 제외 하고 synchronized lockvolatile 원칙 을 통 해 암시 적 인 보증 순서 성 을 가진다.
    그 중 하 나 는 JVM 키워드 에 적용 되 는 것 으로 happen-before 키 워드 를 대상 으로 하 는 쓰기 동작 은 읽 기 동작 전에 읽 은 값 이 최신 일 것 이다.
    volatile 의 응용
    이중 검사 자물쇠 의 단일 모드volatile 으로 이중 검사 잠 금 의 단일 모드 를 실현 할 수 있 습 니 다.
        public class Singleton {
            private static volatile Singleton singleton;
    
            private Singleton() {
            }
    
            public static Singleton getInstance() {
                if (singleton == null) {
                    synchronized (Singleton.class) {
                        if (singleton == null) {
                            singleton = new Singleton();
                        }
                    }
                }
                return singleton;
            }
    
        }

    이곳 의 volatile 키 워드 는 주로 명령 의 재 배열 을 방지 하기 위 한 것 이다.만약 에 volatile,volatile 을 사용 하지 않 으 면 이 코드 는 사실은 세 단계 로 나 뉜 다.
  • 메모리 공간 을 분배 합 니 다.(1)
  • 대상 을 초기 화 합 니 다.(2)
  • volatile 대상 을 분 배 된 메모리 주 소 를 가리킨다.(3)

  • 게다가 singleton = new Singleton(); 은 상기 세 단계 의 조작 순 서 를 집행 하기 위해 서 이 며,반대로 세 번 째 단계 가 두 번 째 단계 이전에 실 행 될 경우 특정한 스 레 드 가 받 은 단일 대상 이 초기 화 되 지 않 아 사용 오류 가 발생 할 수 있다.
    스 레 드 정지 표시 제어
        private volatile boolean flag ;
        private void run(){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    doSomeThing();
                }
            });
        }
    
        private void stop(){
            flag = false ;
        }

    여기 서 만약 volatile 로 flag 를 수식 하지 않 았 다 면,그 중의 한 라인 이 singleton 방법 으로 flag 의 값 을 수정 하여 주 메모리 에 바로 갱신 하지 않 았 을 수도 있 고,이 순환 이 즉각 멈 추 지 않 았 을 수도 있다.
    이곳 에서 주로 이용 하 는 것 은 volatile 의 메모리 가시 성 이다.
    요약:-stop() 키 워드 는 가시 성,순서 성 만 보장 할 수 있 고 원자 성 을 보장 할 수 없습니다.

    좋은 웹페이지 즐겨찾기