>  기사  >  Java  >  Java 높은 동시성의 휘발성 및 Java 메모리 모델은 무엇입니까?

Java 높은 동시성의 휘발성 및 Java 메모리 모델은 무엇입니까?

PHPz
PHPz앞으로
2023-04-30 23:46:151531검색

public class Demo09 {	
    public static boolean flag = true;	
    public static class T1 extends Thread {	
        public T1(String name) {	
            super(name);	
        }	
        @Override	
        public void run() {	
            System.out.println("线程" + this.getName() + " in");	
            while (flag) {	
                ;	
            }	
            System.out.println("线程" + this.getName() + "停止了");	
        }	
    }	
    public static void main(String[] args) throws InterruptedException {	
        new T1("t1").start();	
        //休眠1秒	
        Thread.sleep(1000);	
        //将flag置为false	
        flag = false;	
    }	
}

위 코드를 실행해 보면 프로그램이 종료되지 않는 것을 확인할 수 있습니다.

스레드 t1의 run() 메소드에 루프가 있습니다. 이 플래그는 루프 종료 여부를 제어하는 ​​데 사용됩니다. 메인 스레드는 1초 동안 휴면 상태를 유지하며 이때 플래그를 false로 설정한다고 합니다. t1은 플래그가 false임을 감지하고 "Thread t1이 중지되었습니다"를 인쇄합니다. 결과가 예상한 것과 다른 이유는 무엇입니까? 위의 코드를 실행하면 t1에 보이는 플래그가 항상 true인지 판단할 수 있습니다. 메인 스레드가 플래그를 false로 설정한 후에는 t1 스레드에 표시되지 않으므로 계속 반복됩니다.

그렇다면 왜 t1의 메인 스레드에 의해 수정된 플래그를 볼 수 없나요?

이를 설명하려면 먼저 JMM(Java Memory Model)을 이해해야 합니다. Java 스레드 간의 통신은 Java 메모리 모델(이 문서에서는 JMM이라고 함)에 의해 제어됩니다. JMM은 스레드가 공유에 쓰는 시기를 결정합니다. 변수는 다른 스레드에 작성되어야 합니다. 추상적인 관점에서 JMM은 스레드와 주 메모리 간의 추상 관계를 정의합니다. 스레드 간의 공유 변수는 주 메모리(주 메모리)에 저장되며 각 스레드는 공유 메모리의 복사본인 개인 로컬 메모리(로컬 메모리)를 갖습니다. 스레드가 읽고 쓰는 변수는 로컬 메모리에 저장됩니다. 로컬 메모리는 JMM의 추상적인 개념이며 실제로 존재하지 않습니다. 캐시, 쓰기 버퍼, 레지스터, 기타 하드웨어 및 컴파일러 최적화를 다룹니다. Java 메모리 모델의 추상적 개략도는 다음과 같습니다.

Java 높은 동시성의 휘발성 및 Java 메모리 모델은 무엇입니까?

위 그림에서 볼 수 있듯이 스레드 A는 스레드 B와 통신해야 하며 다음 2단계를 거쳐야 합니다.

1. 스레드 A는 로컬 메모리 A를 저장합니다. 업데이트된 공유 변수는 메인 메모리로 플러시됩니다

2. 그런 다음 스레드 B는 스레드 A가 이전에 업데이트한 공유 변수를 읽기 위해 메인 메모리로 이동합니다

다음은 다음 두 단계를 설명합니다.

Java 높은 동시성의 휘발성 및 Java 메모리 모델은 무엇입니까?

위 그림에 표시된 것처럼 로컬 메모리 A와 B는 주 메모리에 공유 변수 x의 복사본을 가지고 있습니다. 처음에는 이 세 메모리의 x 값이 모두 0이라고 가정합니다. 스레드 A가 실행 중일 때 업데이트된 x 값(값이 1이라고 가정)을 자체 로컬 메모리 A에 임시 저장합니다. 스레드 A와 스레드 B가 통신해야 할 때 스레드 A는 먼저 로컬 메모리의 수정된 x 값을 주 메모리로 새로 고칩니다. 이때 주 메모리의 x 값은 1이 됩니다. 이후 스레드 B는 스레드 A의 업데이트된 x 값을 읽기 위해 메인 메모리로 이동합니다. 이때 스레드 B의 로컬 메모리의 x 값도 1이 됩니다. 전반적으로 이 두 단계는 본질적으로 스레드 A가 스레드 B에 메시지를 보내는 것이며 이 통신 프로세스는 메인 메모리를 거쳐야 합니다. JMM은 기본 메모리와 각 스레드의 로컬 메모리 간의 상호 작용을 제어하여 Java 프로그래머에게 메모리 가시성을 보장합니다.

JMM을 이해한 후 기사 시작 부분의 질문을 살펴보겠습니다. 스레드 t1의 메인 스레드에 의해 플래그 값이 false로 수정된 것을 볼 수 없는 이유는 다음과 같습니다.

1. 스레드는 플래그를 수정하지만 주 메모리로 새로 고쳐지지 않으므로 t1은 이를 볼 수 없습니다.

2. 주 스레드는 플래그를 주 메모리로 새로 고치지만 t1은 자체 작업 메모리에서 플래그 값을 계속 읽고 수행합니다. 최신 플래그를 얻기 위해 메인 메모리로 가지 마세요

위의 두 가지 상황을 해결할 수 있는 방법이 있나요?

이런 방법이 있나요? 스레드가 작업 메모리의 복사본을 수정한 후 작업 메모리에서 공유 변수를 읽을 때마다 즉시 주 메모리로 새로 고쳐지고 다시 주 메모리에서 읽혀집니다. , 작업 메모리에 복사를 차례로 클릭합니다.

Java는 휘발성을 사용하여 공유 변수를 수정하면 위와 같은 효과를 얻을 수 있습니다. 휘발성으로 수정된 변수는 다음과 같은 특징을 갖습니다.

1 스레드를 읽을 때마다 다음으로 이동합니다. 공유 변수의 최신 값을 읽어서 작업 메모리에 복사합니다.

2. 스레드는 작업 메모리에 있는 변수의 복사본을 수정한 후 즉시 메인 메모리에 새로 고쳐집니다. memory

시작 부분을 수정해 보겠습니다. 샘플 코드:

public volatile static boolean flag = true;

휘발성을 사용하여 플래그 변수를 수정한 다음 프로그램을 실행합니다. 출력은 다음과 같습니다.

线程t1 in	
线程t1停止了

이제 프로그램이 정상적으로 중지될 수 있습니다. Volatile은 다중 스레드에서 공유 변수의 가시성 문제를 해결합니다. 가시성은 한 스레드의 공유 변수 수정이 다른 스레드에서 표시되는지 여부를 나타냅니다.

위 내용은 Java 높은 동시성의 휘발성 및 Java 메모리 모델은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제