"로컬"변수와 "공유"변수는 코드 컨텍스트 외부에서 의미가 없습니다. 상태가 캐시되는 위치 또는 영향을받지 않습니다. 국가가 어디에 저장되어 있는지 생각하거나 추론하는 것은 유용하지 않습니다. JMM이 존재하는 모든 이유는 아키텍처와 아키텍처에 따라 달라지는 이러한 세부 사항이 프로그래머에게 노출되지 않도록하기 위해서입니다. 저수준 하드웨어 세부 사항에 의존함으로써 JMM에 대한 잘못된 질문을하고 있습니다. 응용 프로그램에 유용하지 않으며, 깨지기 쉽고, 깨지기 쉽고, 추론하기가 어려우며, 이식성이 떨어집니다.
그렇다면 일반적으로 모든 상태가 아닌 모든 프로그램 상태가 캐시 될 수 있다고 가정해야합니다. 실제로 캐시 된 것은 실제로 중요하지 않으며, 기본 유형이든 참조 유형이든 또는 여러 필드로 캡슐화 된 상태 변수 일지라도 모든 것이 될 수 있습니다. 스레드가 실행하는 명령어가 무엇이든간에 (아키텍처에 따라 그 명령어가 다르다 조심하십시오!), 명령어는 CPU와 관련하여 캐시와 관련된 내용과 캐시하지 않을 내용을 다시 지정합니다. 프로그래머가 스스로 이것을 할 수는 없습니다 (은 입니다. 영향, 상태 변수가 캐시 될 수 있습니다, false sharing 참조).
다시 말하지만, 우리는 또한 활성 기본 유형은 P/ALU가 가장 빠른 그들과 함께 작업 할 수 있기 때문에 아마 레지스터에 넣어 것으로, 86에 대해 좀 더 일반화 할 수 있습니다. 다른 것은 그나저 간다. 코어 - 로컬 인 경우 프리 머 티브를 L1/2 캐시로 옮길 수 있습니다. 확실히 덮어 쓰기가 가능합니다. CPU는 장래 컨텍스트 스위치가있을 것이라고 생각하면 공유 L3에 상태 변수를 넣을 수 있습니다. 하드웨어 전문가가 이에 대응해야합니다.
이상적으로 상태 변수는 가장 가까운 캐시 (레지스터, L1/2/3, 메인 메모리)에 프로세서 장치에 저장하는 것이 이상적입니다. 그것은 CPU를 결정하는 것입니다. Java 레벨에서 캐시 시맨틱에 대한 이유는 불가능합니다. 비록 하이퍼 스레딩이 가능하다 할지라도 (나는 AMD가 무엇인지는 모르겠다.), 쓰레드는 리소스를 공유 할 수 없으며, 그렇다고하더라도 공유 상태 변수와 관련된 유일한 문제는 가시성이 아니라는 점을 기억해야한다. 프로세서가 파이프 라이닝을 수행하는 경우 올바른 순서 (이 경우에도 CPU에서 읽기/쓰기 버퍼링을 제거한 후에도)가 올바른지 확인하려면 적절한 지침이 필요합니다 (hwsync
또는 적절한 울타리인지 여부).
캐시의 속성에 대한 추론은 유용하지 않습니다. JMM이 캐시를 처리 할 수 없기 때문에 캐시가 처리되지 않기 때문에 및을 처리하기 때문입니다. 또한 어디/언제/어떤 질문을 알고 있더라도 STILL은 데이터 가시성에 대해 판단 할 수 없습니다. 모든 캐시는 어쨌든 캐시 된 데이터를 처리하므로 ME (O) SI 상태, 명령어 순서,로드/저장 버퍼링, 다시 쓰 기/통과 등의 캐시 상태를 업데이트하는 프로세서에 의존해야합니다. 여전히 OS 및 JVM 수준에서 발생할 수있는 문제는 아직 다루지 않았습니다. 다행히도 JDK에서는 volatile
, final
과 같은 기본 도구를 사용할 수 있으며 모든 플랫폼에서 일관되게 작동하는 원자와 예측 가능하고 쉬운 (쉽게) 코드를 생성 할 수 있습니다.
원시 타입이 아닌 경우, * "변수 값"*은 Java의 * references-to * 객체 일뿐입니다. * 객체 자체는 스택에 없습니다. 필드는 항상 객체 *와 연관되어 * 객체 *가 스택에 없으므로 * Java 메모리 모델은 필드 읽기/쓰기와의 관계에 다소 관대합니다. 스레드 가시성 문제가 자주 발생합니다 . – user2864740
주제가 SO 질문에 비해 너무 광범위하고 불특정이지만 몇 가지 잘못된 가정이 있습니다. "로컬 변수 - 스레드 스택": 개념적 Java 아키텍처로 코드가 실제로 CPU에서 실행되는 방식과 거의 관련이 없습니다. 그러나 대부분의 경우 메인 메모리에 저장되고 CPU 캐시에 캐싱 될 수 있습니다. 다른 스레드와 공유되지 않습니다. "공유 변수 - 메모리에 있지만 모든 CPU 캐시에는 복사본이 있습니다"- 아니요, CPU 캐시는 그다지 크지 않습니다. 해당 CPU가 해당 데이터를 사용할 때만 데이터를로드합니다. –