Java 메모리 모델은 작업 메모리에 있는 변수의 수정된 값을 메인 메모리에 동기화하고, 변수를 읽기 전에 메인 메모리에서 작업 메모리로 최신 값을 새로 고치는 방식으로 가시성을 확보합니다. 가시성을 확보하기 위한 메인 메모리.차이점: 1. Volatile은 스레드 차단을 유발하지 않지만 동기화되면 스레드 차단이 발생할 수 있습니다. 2. Volatile은 데이터의 가시성을 보장하지만 원자성을 보장할 수 없는 반면, 동기화는 원자성을 보장하고 간접적으로 가시성을 보장합니다. 가시성: 하나의 스레드가 공유 변수를 수정한 후 다른 스레드가 즉시 변수의 수정(변경)을 볼(인식) 수 있습니다.
원자성 원자성:
모든 실행이 완료되거나 실행되지 않아 작업을 중단할 수 없습니다. Java 메모리 모델이 보장하는 것은 동일한 스레드 내의 모든 작업이 위에서 아래로 진행된다는 것입니다. 그러나 여러 스레드가 병렬로 실행되는 경우 해당 작업의 순서가 보장될 수 없습니다.
순서성순서성:
이 스레드에서 관찰된 작업은 모두 순서가 지정되어 있습니다. 한 스레드의 다른 스레드에서 관찰되면 모든 작업은 순서가 지정되지 않습니다.Java 메모리 모델이 보장하는 것은 동일한 스레드 내의 모든 작업이 위에서 아래로 진행된다는 것입니다. 그러나 여러 스레드가 병렬로 실행되는 경우 해당 작업의 순서가 보장될 수 없습니다.
컴퓨터가 프로그램을 실행할 때 성능 향상을 위해 컴파일러와 프로세서는
를 재배열하는 경우가 많습니다. 이는 일반적으로 다음 세 가지 유형으로 나뉩니다. 단일 스레드 환경에서 최종 실행 결과는 프로그램과 코드 실행 결과가 일관성 있게 보장됩니다. 프로세서는 재정렬 시 명령어 간의
데이터 종속성을 고려해야 합니다.다중 스레드 환경에서는 스레드가 교대로 실행됩니다. 컴파일러 최적화 재정렬이 존재하기 때문입니다. 변수가 일치하는지 판단하는 것도 불가능하고 결과도 예측할 수 없습니다 시험에서 할 수 있는 일을 먼저 하고 할 수 없는 일을 나중에 하세요.
public void mySort(){ int x = 11; //1 int y = 12; //2 x= x+5; // 3 y = x*x;//4
가능한 순서는 1234 2134 1324이며, 속성 4가 1과 3 앞에 올 수 없습니다.
데이터 종속성이 있기 때문입니다.
휘발성은 명령 재정렬을 금지합니다.
public class ReSortSeqDemo { int a = 0; boolean flag = false; public void method01() { a = 1; // flag = true; // ----线程切换---- flag = true; // a = 1; } public void method02() { if (flag) { a = a + 3; System.out.println("a = " + a); } } }두 스레드가 동시에 실행되는 경우 스레드 1이 method01을 실행하면 method01과 method02가 재정렬되고, 전환된 스레드 2가 method02를 실행하면 다른 결과가 나타납니다.
휘발성은 명령어 재정렬 금지 최적화를 실현하여 멀티스레드 환경에서 프로그램 장애 현상을 방지합니다
먼저 개념을 이해하세요. 메모리 장벽은 두 가지 기능을 가진 CPU 명령어입니다.
특정 변수의 메모리 가시성 보장(휘발성 메모리 가시성을 확보하려면 이 기능을 사용하세요)
컴파일러가 명령어 재정렬 최적화를 수행할 수 있기 때문입니다. 명령어 사이에 메모리 배리어가 삽입되면 이 메모리 배리어 명령어로 명령어를 재정렬할 수 없음을 컴파일러와 CPU에 알립니다. 즉, 메모리 배리어를 삽입하면 메모리 배리어 전후에 재정렬을 실행하는 것이 금지됩니다. 정렬 최적화. 메모리 장벽의 또 다른 기능은 다양한 CPU 캐시 데이터를 강제로 플러시하여 CPU의 모든 스레드가 이러한 데이터의 최신 버전을 읽을 수 있도록 하는 것입니다.다음은 보존적 전략에 따라 휘발성 쓰기가 메모리 장벽을 삽입한 후 생성된 명령 시퀀스의 개략도입니다. 다음은 보존적 전략에 따라 휘발성 읽기가 메모리 장벽을 삽입한 후 생성된 명령 시퀀스의 개략도입니다. :
스레드 안전성 가시성 보장
작업 메모리와 메인 메모리 간의 동기화 지연으로 인해 가시성 문제가 발생함
이는 한 스레드에서 수정된 변수를 사용하여 즉시 동기화할 수 있는 syncronzied 또는 휘발성 키워드를 사용하여 해결 가능 다른 스레드에 표시됨 명령 재배열로 인한 가시성 문제 및 순서 문제
는 휘발성 키워드를 사용하여 해결할 수 있습니다. 휘발성의 또 다른 기능은 명령 재정렬 최적화를 금지하는 것이기 때문입니다
휘발성
변수
it가 수정합니다. 복사본을 유지하지 않고 메모리의 메인에 직접 액세스합니다
.
Java 메모리 모델에는 주 메모리가 있고, 각 스레드에는 자체 메모리(예: 레지스터)도 있습니다. 성능을 위해 스레드는 액세스하는 변수의 복사본을 자체 메모리에 보관합니다. 이런 식으로 한 스레드의 메모리에 있는 동일한 변수의 값이 다른 스레드의 메모리에 있는 값이나 특정 순간의 메인 메모리에 있는 값과 일치하지 않는 상황이 발생할 수 있습니다. 변수를 휘발성으로 선언한다는 것은 변수가 언제든지 다른 스레드에 의해 수정될 수 있으므로 스레드 메모리에 캐시될 수 없음을 의미합니다.
사용 시나리오
제한된 상황에서는 휘발성 변수만 사용하여 잠금을 대체할 수 있습니다. 휘발성 변수가 이상적인 스레드 안전성을 제공하려면 다음 두 가지 조건이 동시에 충족되어야 합니다.
1) 변수에 대한 쓰기 작업은 현재 값에 의존하지 않습니다.
2) 해당 변수는 다른 변수와의 불변성에 포함되지 않습니다.
휘발성은 하나의 스레드가 쓰고 여러 스레드가 읽는 상황에 가장 적합합니다.
여러 스레드가 동시에 작성되는 경우에도 잠금이나 스레드로부터 안전한 컨테이너 또는 원자 변수를 대신 사용해야 합니다.
synchronized
메서드나 코드 블록을 수정하는 데 사용되는 경우 최대 한 개의 스레드가 동시에 코드를 실행하는지 보장할 수 있습니다.
Lock
jdk 5.0부터 Java는 더욱 강력한 스레드 동기화 메커니즘을 제공합니다. 동기화는 동기화 잠금 개체를 명시적으로 정의하여 달성되며 동기화 잠금은 잠금 개체로 작동합니다. java.util.concurrent.Locks.Lock 인터페이스는 공유 리소스에 대한 여러 스레드의 액세스를 제어하는 도구입니다. 잠금은 공유 리소스에 대한 단독 액세스를 제공합니다. 한 번에 하나의 스레드만 잠금 개체를 잠글 수 있습니다. 스레드는 공유 리소스에 액세스하기 시작하기 전에 잠금 개체를 얻어야 합니다. ReentrantLock 클래스는 동기화와 동일한 동시성 및 메모리 의미를 갖는 Lock을 구현합니다. 스레드 안전 제어를 구현할 때 ReentrantLock이 더 일반적으로 사용되며 잠금을 표시하고 잠금을 해제할 수 있습니다.차이점
휘발성과 동기화
휘발성은 변수 수정자인 반면, 동기화는 코드나 메소드에 따라 작동합니다.
휘발성은 데이터의 가시성을 보장하지만 원자성을 보장할 수 없습니다. 동기화는 개인 메모리와 공용 메모리의 데이터를 동기화하므로 원자성을 보장하고 간접적으로 가시성을 보장할 수도 있습니다.
휘발성 키워드는 여러 스레드가 인스턴스 변수가 수정되었음을 감지하고 최신 값을 얻을 수 있을 때 주로 사용됩니다. 즉, 여러 스레드가 공유 변수를 읽을 때 최신 값을 얻을 수 있습니다.
예: i++, 즉 i=i+1이면 이러한 작업은 실제로 원자적 작업이 아닙니다. 즉, 스레드로부터 안전하지 않습니다. i++ 표현식의 작업 단계는 다음과 같이 분류됩니다.
1) 메모리에서 i 값을 가져옵니다.
2) i의 값을 계산합니다.
3) i의 값을 메모리에 씁니다.
2단계에서 값을 계산할 때 다른 스레드도 i 값을 수정하면 이때 더티 읽기 데이터가 이름으로 나타납니다. 해결책은 동기화된 키워드를 사용하는 것입니다. 그래서 휘발성 자체는 데이터의 원자성을 처리하지 않지만 데이터 읽기 및 쓰기가 적시에 메인 메모리에 영향을 미치도록 강제합니다.
synchronized and Lock
Lock은 명시적 잠금(수동으로 열고 닫고, 잠금을 끄는 것을 잊지 마세요)이고, 동기화는 암시적 잠금이며, 잠금은 범위를 벗어나면 자동으로 해제됩니다. .
Lock은 코드 블록만 잠그고 동기화는 코드 블록 및 메소드에서 작동할 수 있습니다.
잠금 잠금을 사용하면 jvm은 스레드 예약에 소요되는 시간을 줄이고 성능을 향상시킵니다. 확장성이 더 좋습니다(더 많은 하위 클래스 제공).
사용 순서: 잠금 -> 동기화된 코드 블록(메소드 본문에 진입하고 해당 리소스를 할당함) -> 동기화된 메서드(메서드 본문 외부).
더 많은 프로그래밍 관련 지식을 보려면 프로그래밍 학습 코스를 방문하세요! !
위 내용은 휘발성과 동기화의 차이점은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!