Java 스레드 동시성 처리에서 키워드 휘발성을 사용하는 데 많은 혼란이 있습니다. 이 키워드를 사용하면 다중 스레드 동시성 처리를 사용할 때 모든 것이 잘 될 수 있다고 생각합니다.
Java 언어는 멀티 스레딩을 지원합니다. 스레드 동시성 문제를 해결하기 위해 언어 내부에 동기 블록 및 휘발성 키워드 메커니즘이 소개됩니다.
동기화
모든 사람은 동기화 된 블록에 익숙하며 동기화 된 키워드를 통해 구현됩니다. 동기화 및 블록 문을 사용하면 멀티 스레드에 액세스 할 때 동시에 하나의 스레드 만 사용할 수 있습니다.
동기화 된 수정 된 메소드 또는 코드 블록.
휘발성 물질
휘발성으로 수정 된 변수의 경우 스레드는 변수를 사용할 때마다 변수의 가장 수정 된 값을 읽습니다. 휘발성은 쉽게 오용되어 원자 연산에 사용됩니다.
아래 예를 봅시다. 우리는 카운터를 구현합니다. 스레드가 시작될 때마다 Counter Inc 메소드가 호출되어 카운터에 하나를 추가합니다.
실행 환경 -JDK 버전 : JDK1.6.0_31, 메모리 : 3G CPU : X86 2.4G
public class counter {public static int count = 0; public static void inc () {// 여기 지연은 1 밀리 초입니다. 결과는 명백한 시도 {thread.sleep (1);} catch (interpruptedException e) count ++;} 공동 정적 void main (string [] args) {// int i++collections에서 시작하는 것, int i++collections에서 시작합니다. i <1000; i ++) {new Thread (new runnable () {@overridepublic void run () {counter.inc ();}}). start ();} // 각 실행 값은 다를 수 있으며, 1000system.out.println ( "실행 결과 : counter.count .count);}};실행 결과 : counter.count = 995
실제 작동 결과는 매번 다를 수 있습니다. 기계의 결과는 다음과 같습니다. 실행 결과 : counter.count = 995. 다중 스레드 환경에서 카운트가 결과가 1000이 될 것으로 예상하지 않는다는 것을 알 수 있습니다.
많은 사람들은 이것이 다중 스레드 동시성 문제라고 생각합니다. 이 문제를 피하기 위해 변수 수를 계산하기 전에 휘발성을 추가하면됩니다. 그런 다음 결과가 기대에 부응하는지 확인하기 위해 코드를 수정하고 있습니다.
홍보 카운터 {공개 휘발성 정적 int count = 0; public static void inc () {// 여기 지연은 1 밀리 초이며, 결과는 {thread.sleep (1);} catch (interpruptedException e) count ++;} 공동 정적 무효 메인 (String [] args) {// 동일한 시간에 1,000 스레드를 시작하고, I ++ 계산, 그리고, I ++ 계산, 그리고, I ++++계산, 그리고, I +++보다, = 0; i <10; i ++;실행 결과 : counter.count = 992
작업 결과는 여전히 우리가 예상했던 것보다 1000이 아닙니다. 아래 이유를 분석 해 봅시다
Java Garbage Collection 기사에서 JVM의 순간에 메모리 할당이 설명되어 있습니다. 메모리 영역 중 하나는 JVM 가상 머신 스택이며 각 스레드에는 실행될 때 스레드 스택이 있습니다.
스레드 스택은 스레드 런타임 중에 가변 값 정보를 저장합니다. 스레드가 특정 객체의 값에 액세스하면 먼저 객체의 참조를 통해 힙 메모리에 해당하는 변수의 값을 찾은 다음 힙 메모리를 넣습니다.
변수의 특정 값은 스레드의 로컬 메모리에로드되며 변수의 사본이 생성됩니다. 그 후, 스레드는 더 이상 힙 메모리에서 객체의 변수 값과 관계가 없지만 사본 변수의 값을 직접 수정합니다.
수정 후 특정 순간에 (스레드가 종료되기 전), 스레드 변수 사본의 값은 힙의 객체 변수로 자동으로 기록됩니다. 이렇게하면 힙 내 물체의 값이 변경됩니다. 다음 그림
기본 메모리에서 현재 작업 메모리까지 복사 변수를 읽고로드합니다.
공유 변수 값을 변경하려면 실행 코드 사용 및 할당
작업 메모리 데이터로 새로 고침 메인 메모리 관련 콘텐츠를 저장 및 쓰기
사용 및 할당이 여러 번 나타날 수 있습니다
그러나 이러한 작업은 원자가 아니며, 즉 읽기 부하 후, 메인 메모리 수 변수가 수정되면 스레드 작업 메모리의 값이로드 된 이후 해당 변경 사항을 유발하지 않으므로 계산 된 결과는 예상과 다릅니다.
휘발성에 의해 수정 된 변수의 경우 JVM 가상 머신은 기본 메모리에서 스레드 작업 메모리로로드 된 값이 최신임을 보장합니다.
예를 들어, 스레드 1과 스레드 2가 읽기 및로드 작업을 수행하고 메인 메모리의 카운트 값이 5라는 것을 알면 최신 값이로드됩니다.
힙 계수가 스레드 1에서 수정되면 주 메모리에 기록되며 기본 메모리의 카운트 변수는 6이됩니다.
스레드 2는 이미 읽기 및로드 작업을 수행 했으므로 메인 메모리 카운트의 변수 값도 작업 후 6으로 업데이트됩니다.
이로 인해 두 개의 스레드가 휘발성 키워드를 제 시간에 수정 한 후 동시성이 발생합니다.
위는 편집자가 소개 한 Java의 휘발성 키워드의 의미입니다. 나는 그것이 당신에게 도움이되기를 바랍니다. 궁금한 점이 있으면 메시지를 남겨 주시면 편집자가 제 시간에 답장을 드리겠습니다. Wulin.com 웹 사이트를 지원해 주셔서 대단히 감사합니다!