>  기사  >  Java  >  Java 높은 동시성에서 휘발성 구현 원리에 대한 자세한 소개

Java 높은 동시성에서 휘발성 구현 원리에 대한 자세한 소개

黄舟
黄舟원래의
2017-03-30 10:26:131517검색

이 기사에서는 주로 Java 높은 동시성에서 휘발성의 구현 원리에 대한 관련 정보를 소개합니다. 동시 프로그래밍 동기화 및 Volatile은 모두 중요한 역할을 합니다. 다중 프로세서 개발에서 공유 변수 의 "가시성"이 필요한 친구는

Java 높은 동시성에서 휘발성 구현 원리

추상: 다중 스레드 동시 프로그래밍에서 동기화 및 휘발성 모두 중요한 역할을 합니다. Volatile은 다중 프로세서 개발에서 변수 공유를 보장하는 경량 동기화입니다. 가시성은 한 스레드가 공유 변수를 수정할 때 다른 스레드가 수정된 값을 읽을 수 있음을 의미합니다. 어떤 경우에는 동기화보다 오버헤드가 적습니다

1. 정의:

java

프로그래밍 언어스레드가 공유 변수에 액세스할 수 있도록 허용합니다. 공유 변수가 정확하고 일관되게 업데이트될 수 있도록 스레드는 이 변수가 배타적 잠금을 통해 개별적으로 획득되도록 해야 합니다. Java 언어는 일부 상황에서는 잠금보다 더 편리한 휘발성을 제공합니다. 필드가 휘발성으로 선언되면 Java 스레드 메모리 모델 은 모든 스레드가 이 변수의 동일한 값을 볼 수 있도록 보장합니다

2. 휘발성 구현 원칙

그럼 Volatile은 어떻게 가시성을 보장하나요? x86 프로세서에서는 도구를 사용하여 JIT 컴파일러에서 생성된 어셈블리 지침을 가져와 Volatile에 쓸 때 CPU가 수행하는 작업을 확인합니다.

Java 코드: 인스턴스 = new Singleton();//인스턴스는 휘발성 변수입니다

어셈블리 코드: 0x01a3de1d: movb $0x0,0x1104800(% esi );0x01a3de24: lock addl $0x0,(%esp);

휘발성 변수로 수정된 공유 변수가 작성되면 어셈블리 코드의 두 번째 줄은 IA-32

아키텍처 소프트웨어 개발자 매뉴얼을 확인하면 접두사가 붙은 잠금 명령이 멀티 코어 프로세서에서 두 가지를 유발한다는 것을 알 수 있습니다.

현재 프로세서의

캐시 행의 데이터가 시스템 메모리에 다시 기록됩니다.

이 다시 쓰기 작업으로 인해 다른 CPU의 이 메모리 주소에 캐시된 데이터가 유효하지 않게 됩니다.

처리 속도를 높이기 위해 프로세서는 메모리와 직접 통신하지 않고, 작업을 수행하기 전에 먼저 시스템 메모리의 데이터를 내부 캐시(L1, L2 등)로 읽어옵니다. , 그러나 작업이 완료된 후에는 알 수 없습니다. 선언된 Volatile 변수에 대해 쓰기 작업이 수행되면 JVM은 캐시에 데이터를 쓰기 위해 Lock 접두어 명령을 보냅니다. 변수가 시스템 메모리에 다시 위치하는 줄입니다. 그러나 메모리에 다시 기록하더라도 다른 프로세서에서 캐시한 값이 여전히 오래되면 계산 작업을 수행할 때 문제가 발생합니다. 따라서 다중 프로세서에서는 각 프로세서의 캐시를 보장하기 위해 일관성이 있으면 캐시 일관성이 달성됩니다. 각 프로세서는 버스에 업로드된 데이터를 검사하여 캐시된 값이 만료되었는지 여부를 확인합니다. 프로세서는 캐시 라인에 해당하는 메모리 주소가 수정되었음을 발견합니다. 프로세서의 캐시 라인이 유효하지 않은

상태로 설정되었습니다. 프로세서가 이 데이터를 수정하려고 하면 강제로 시스템 메모리의 데이터를 프로세서 캐시로 다시 읽어야 합니다. 접두사 잠금 명령을 사용하면 프로세서 캐시가 메모리에 다시 기록됩니다. Lock 접두어 명령어는 명령어 실행 중에 프로세서의 LOCK# 신호가 발생하도록 합니다. 다중 프로세서 환경에서 LOCK# 신호는 신호가 어설션되는 동안 프로세서가 모든 공유 메모리를 독점적으로 사용하도록 보장합니다. (버스를 잠그기 때문에 다른 CPU가 버스에 접근할 수 없게 됩니다. 버스에 접근할 수 없다는 것은 시스템 메모리에 접근할 수 없다는 것을 의미합니다.) 그러나 최근 프로세서에서는 일반적으로 LOCK# 신호가 버스를 잠그지 않습니다. , 그러나 캐시를 잠급니다. 결국 잠금은 버스 오버헤드가 상대적으로 큽니다. 프로세서 캐시에 대한 잠금 작업의 영향은 8.1.4장에 자세히 설명되어 있습니다. Intel486 및 Pentium 프로세서의 경우 잠금 작업 중에 LOCK# 신호가 항상 버스에 표시됩니다. 그러나 P6 및 최신 프로세서에서는 액세스되는 메모리 영역이 이미 프로세서 내에 캐시되어 있는 경우 LOCK# 신호가 어설션되지 않습니다. 대신, 이 메모리 영역의 캐시를 잠그고 이를 메모리에 다시 쓰고 캐시 일관성 메커니즘을 사용하여 수정의 원자성을 보장합니다. 이 작업을 "캐시 잠금"이라고 합니다. 캐시 일관성 메커니즘은 동시 수정이 방지됩니다. 2개 이상의 프로세서에 의해 캐시된 메모리 영역 데이터.

한 프로세서의 캐시를 메모리에 다시 쓰면 다른 프로세서의 캐시가 무효화됩니다. IA-32 프로세서와 Intel 64 프로세서는 MESI(수정, 독점, 공유, 무효화) 제어 프로토콜을 사용하여 내부 캐시와 다른 프로세서 캐시 간의 일관성을 유지합니다. 멀티 코어 프로세서 시스템에서 작동할 때 IA-32 및 Intel 64 프로세서는 시스템 메모리 및 내부 캐시에 대한 다른 프로세서의 액세스를 탐지할 수 있습니다. 그들은 스니핑 기술을 사용하여 내부 캐시, 시스템 메모리 및 기타 프로세서 캐시의 데이터가 버스에서 일관성을 유지하는지 확인합니다. 예를 들어 Pentium 및 P6 제품군 프로세서에서 다른 프로세서가 현재 공유 상태를 처리하는 메모리 주소에 쓰려고 한다는 것을 감지하기 위해 한 프로세서를 스니핑하면 스니핑 프로세서는 다음과 같이 캐시 라인을 무효화합니다. 🎜> 동일한 메모리 주소에 접근할 때마다

위 내용은 Java 높은 동시성에서 휘발성 구현 원리에 대한 자세한 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.