아 리 의 자바 와 함께 시험 문 제 를 상세 하 게 풀 었 다.

제목.
저 는 개인 적 으로 인터넷,병발 과 관련 된 지식 이 다른 프로 그래 밍 지식 에 비해 더 어렵다 고 생각 합 니 다.주로 디 버 깅 하기 어렵 고 관련 내용 이 너무 많 습 니 다!
그래서 오늘 은 병발 과 관련 된 내용 을 한 편 가지 고 공유 하 겠 습 니 다.여러분 이 열심히 보시 면 얻 을 수 있 을 거 라 고 믿 습 니 다.
여러분 은 먼저 이 문 제 를 보고 이것 에 문제 가 있 는 지 볼 수 있 습 니까?거기 문제 있 는데?

만약 당신 이 이 문제 에 5s 이상 머 물 렀 다 면,당신 은 이 어떤 지식 에 대해 아직 모호 하 다 는 것 을 나타 내 고,좀 더 공 고 히 해 야 합 니 다.다음은 우리 가 함께 분석 해 보 겠 습 니 다!
결론.
다 중 스 레 드 가 동시에 set,get 작업 을 진행 합 니 다.A 스 레 드 가 set 방법 을 호출 합 니 다.B 스 레 드 가 반드시 이 변 화 를 볼 수 있 는 것 은 아 닙 니 다!!
분석 하 다.
이 종 류 는 매우 간단 합 니 다.그 안에 속성 이 있 습 니 다.두 가지 방법 이 있 습 니 다.get,set 방법,하 나 는 속성 치 를 설정 하고 하 나 는 속성 치 를 가 져 오 며 속성 을 설정 하 는 방법 에 synchronized 를 추가 합 니 다.
암시 적 정보:다 중 스 레 드 가 동시에 set,get 작업 을 하고 A 스 레 드 가 set 방법 을 호출 합 니 다.B 스 레 드 는 안에서 감지 할 수 있 습 니까?
여기까지 만 말 하면 문 제 는 synchronized 가 방금 말 한 문맥 에서 가시 성 을 보장 할 수 있 는 지!!
키워드 synchronized 의 용법
4.567917.잠 금 대상 지정:주어진 대상 에 잠 금 을 추가 하고 동기 코드 에 들 어가 기 전에 주어진 대상 의 잠 금 을 받 아야 합 니 다4.567917.인 스 턴 스 방법 에 직접 작용 합 니 다.현재 인 스 턴 스 에 자 물 쇠 를 추가 하고 동기 코드 에 들 어가 기 전에 현재 인 스 턴 스 의 자 물 쇠 를 얻 는 것 과 같 습 니 다4.567917.정적 방법 에 직접적인 역할 을 합 니 다.현재 클래스 에 자 물 쇠 를 추가 하 는 것 과 같 습 니 다.동기 코드 에 들 어가 기 전에 현재 클래스 의 자 물 쇠 를 얻 어야 합 니 다.
synchronized 의 작업 은 동기 화가 필요 한 코드 에 자 물 쇠 를 추가 하여 매번 하나의 스 레 드 만 동기 화 블록 에 들 어 갈 수 있 도록 하 는 것 입 니 다(사실은 비관 적 인 전략).
여기 서 우 리 는 우리 가 분석 해 야 할 두 번 째 상황 을 알 수 있다.즉,여러 개의 스 레 드 가 set 방법 을 동시에 진행 할 때 자물쇠 가 존재 하기 때문에 하나씩 set 작업 을 하고 스 레 드 가 안전 하지만 get 방법 은 자 물 쇠 를 추가 하지 않 았 다.이 는 A 스 레 드 가 set 를 진행 하 는 동시에 B 스 레 드 가 get 작업 을 할 수 있다 는 것 을 의미한다.또한 여러 스 레 드 가 동시에 get 작업 을 할 수 있 지만 같은 시간 에 최대 하나의 set 작업 만 할 수 있 습 니 다.
자바 메모리 모델 happens-before 원칙
JSR-133 메모리 모델 은 happens-before 의 개념 을 사용 하여 조작 간 의 메모리 가시 성 을 논술 한다.JMM 에서 한 작업 이 실 행 된 결과 가 다른 작업 에 대해 보 여야 한다 면 이 두 작업 사이 에는 happens-before 관계 가 있어 야 합 니 다.여기 서 언급 한 두 가지 조작 은 하나의 스 레 드 안에 있 을 수도 있 고 서로 다른 스 레 드 사이 에 있 을 수도 있다.
프로그래머 와 밀접 한 관 계 를 가 진 happens-before 규칙 은 다음 과 같다.
  • 프로그램 순서 규칙:한 스 레 드 의 모든 작업,happens-before 는 이 스 레 드 에서 의 임의의 후속 작업 입 니 다
  • 4.567917.모니터 잠 금 규칙:모니터 의 잠 금 을 풀 고 happens-before 는 그 다음 에 이 모니터 에 잠 금 을 추가 합 니 다4.567917.volatile 변수 규칙:volatil e 역 에 대한 쓰기,happens-before 는 임의의 후속 으로 이 volatil e 역 에 대한 읽 기
  • 전달 성:A happens-before B,그리고 B happens-before C 가 있다 면 A happens-before C.
  • 주의 하 세 요.두 작업 사이 에 happens-before 관 계 를 가 진 다 는 것 은 앞의 작업 이 반드시 다음 작업 전에 실행 되 어야 한 다 는 것 을 의미 하지 않 습 니 다!happens-before 는 이전 작업(실 행 된 결과)에 만 다음 작업 을 볼 수 있 도록 요구 하고 이전 작업 은 두 번 째 작업 전에 순서대로(the first is visible to and ordered before the second).
    그 중에서 모니터 잠 금 규칙 이 있 습 니 다.모니터 의 잠 금 을 풀 고 happens-before 는 그 다음 에 이 모니터 에 잠 금 을 추가 합 니 다.이것 은 synchronized 의 set 방법 에 대한 것 일 뿐 get 에 대한 설명 은 없습니다.
    사실은 이러한 문맥 아래 synchronized set 방법,일반적인 get 방법,a 스 레 드 호출 set 방법,b 스 레 드 가 반드시 이 변 화 를 볼 수 있 는 것 은 아 닙 니 다!
    volatile
    volatile 가시 성
    앞에서 happens-before 원칙 은 volatile 변수 규칙:volatil e 역 에 대한 쓰기,happens-before 는 임의의 후속 으로 이 volatil e 역 에 대한 읽 기 를 언급 했다.volatile 은 다 중 스 레 드 에서 의 가시 성 을 보장 합 니 다!!
    volatile 메모리 정렬 금지
    다음은 JMM 이 컴 파 일 러 에 대한 volatile 정렬 규칙 표 입 니 다.

    volatile 의 메모리 의 미 를 실현 하기 위해 컴 파일 러 는 바이트 코드 를 생 성 할 때 명령 시퀀스 에 메모리 장벽 을 삽입 하여 특정 유형의 프로세서 정렬 을 금지 합 니 다.
    다음은 보수 정책 을 기반 으로 한 JMM 메모리 장벽 삽입 정책 입 니 다.
  • 모든 volatile 쓰기 동작 앞 에 StoreStore 장벽 을 삽입 합 니 다
  • 모든 volatile 쓰기 동작 뒤에 StoreLoad 장벽 을 삽입 합 니 다
  • 모든 volatile 읽 기 동작 뒤에 Load Load 장벽 을 삽입 합 니 다
  • 모든 volatile 읽 기 동작 뒤에 Loadstore 장벽 을 삽입 합 니 다
  • 다음은 보수 정책 에서 volatile 쓰기 동작 이 메모리 장벽 에 삽 입 된 후 생 성 된 명령 시퀀스 설명도 입 니 다.

    다음은 보수 정책 에서 volatile 읽 기 동작 이 메모리 장벽 에 삽 입 된 후 생 성 된 명령 시퀀스 설명도 입 니 다.

    상기 volatile 쓰기 작업 과 volatile 읽 기 작업 의 메모리 장벽 삽입 전략 은 매우 보수 적 입 니 다.실제 실행 할 때 volatile 쓰기-읽 기 메모리 의 미 를 바 꾸 지 않 으 면 컴 파일 러 는 구체 적 인 상황 에 따라 불필요 한 장벽 을 생략 할 수 있다.
    이중 검사 잠 금 실현 사례 에서 이 특성 을 사용 해 야 합 니 다!!
    모방 하 다
    위의 분석 을 통 해 사실 이 문제 와 관련 된 내용 을 모두 언급 하고 해답 을 했다.
    당신 이 알 고 있 는 이 유 는 알 지만 모 의 하 는 것 은 쉬 운 일이 아 닙 니 다!다음은 효 과 를 모 의 해 보 겠 습 니 다.
    
    public class ThreadSafeCache {
    int result;
    public int getResult() {
    return result;
    }
    public synchronized void setResult(int result) {
    this.result = result;
    }
    public static void main(String[] args) {
    ThreadSafeCache threadSafeCache = new ThreadSafeCache();
    for (int i = 0; i < 8; i++) {
    new Thread(() -> {
    int x = 0;
    while (threadSafeCache.getResult() < 100) {
    x++;
    }
    System.out.println(x);
    }).start();
    }
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    threadSafeCache.setResult(200);
    }
    }
    효과:

    프로그램 은 계속 여기에 걸 려 움 직 이지 않 습 니 다.set 가 수정 한 200,get 방법 이 보이 지 않 습 니 다!!
    volatile 키워드 관찰 효과 추가
    사실 예 에서 synchronized 키 워드 는 지 울 수 있 고 volatile 만 사용 하면 됩 니 다.

    효과:

    코드 가 곧 정상적으로 끝 났 습 니 다!
    결론.
    다 중 스 레 드 가 동시에 set,get 작업 을 하고 A 스 레 드 가 set 방법 을 호출 합 니 다.B 스 레 드 가 반드시 이 변 화 를 볼 수 있 는 것 은 아 닙 니 다!!!위의 코드 에서 get 방법 에 synchronized 를 추가 하 는 것 도 볼 수 있 습 니까?아니면 happens-before 의 모니터 잠 금 규칙 입 니까?모니터 에 대한 잠 금 해제,happens-before 는 그 다음 에 이 모니터 에 대한 잠 금 을 추가 합 니 다.다만 volatile 은 synchronized 보다 경량급 이기 때문에 이 예 는 volatile 을 직접 사용 합 니 다.하지만 비원 자 조작 i++에 부합 되 지 않 는 것 은 synchronized 가 필요 합 니 다.
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기