2012-11-18 4 views
4

의는 다음과 같은 문장을 보자 :Java 컴파일러 또는 JVM이 독립적 인 명령어의 명령어 순서를 바꿀 수 있습니까?

이제
int d0, d1; 
int[] ds = {0, 0}; 

하나 개의 스레드가 다음 지침 :

d0++; 
d1++; 

다른 스레드가이 명령을 가지고있는 동안 :

ds[1] = d1; 
ds[0] = d0; 

우리는 병렬로 이러한 스레드를 실행하는 경우 ds이 {0, 0}, {1, 1} 및 {1, 0}처럼 보일 수있는 세 가지 조합이 분명히 있습니다.

큰 질문은 다음과 같습니다. {0, 1}도있을 수 있습니까? 컴파일러/JVM은 관련이 없다고 생각하기 때문에 명령어를 간단히 바꿀 수 있습니까? 그렇다면, 그러한 행위에 대한 "규칙"은 정확히 무엇이며 컴파일러 또는 JVM에 달려 있습니까?

+1

일반적으로 직렬 (iow, 한 스레드) 모델에서 최적화되지 않은 코드와 동일한 동작을하는 경우 최적화가 안전하다고 간주됩니다. 관련 언어 구문에 스레딩에 대한 명시적인 조항이없는 경우 –

답변

6

예, {0, 1}도 가능합니다. Java 메모리 모델은이 경우 주문을 보장하기에 충분하지 않습니다. 이것은 명령 순서 재조정을 필요로하지 않습니다. x86이나 x86_64 이외의 프로그램에서 프로그램을 실행하면 어쨌든이 명령이 실행됩니다.

여기서 분명히하기 위해 실제 CPU 하드웨어는 x86이 아닌 경우 이러한로드 및 저장을 재정렬합니다.

는 명령 재정렬을 할 수있는 Java Memory Model FAQ

0

예 컴파일러와 JVM 모두 (적시 (just-in-time) 컴파일러)를 참조하십시오. 또한 하드웨어 프로세서가 수행 할 수 있습니다. 원하지 않는 재주문을 방지하려면 memory barriers을 사용해야합니다.

2

적절한 동기화가 없으면 실제로 가능합니다.

Java 언어 사양은 17 장에서 멀티 스레드 Java 프로그램의 의미를 정의합니다.이 장은 이해하기가 어렵지만 신뢰할 수있는 공식 규칙을 포함합니다. 특히, writes :

메모리 모델은 해당 프로그램의 프로그램 및 실행 추적에서 실행 추적이 프로그램의 올바른 실행인지 여부를 설명합니다. Java 프로그래밍 언어 메모리 모델은 실행 추적의 각 읽기를 검사하고 해당 규칙에 따라 해당 읽기에 의해 관찰 된 쓰기가 유효한지 확인하는 방식으로 작동합니다.

메모리 모델은 프로그램의 가능한 동작을 설명합니다. 프로그램의 모든 결과 실행이 메모리 모델에 의해 예측 될 수있는 결과를 생성하는 한, 구현은 원하는 코드를 자유롭게 생성 할 수 있습니다.

메모리 모델은 happens-before relation을 정의하며 모든 재정렬은 consistent with이어야합니다. 서로 다른 스레드에 의해 수행 된 작업에 대해 happen-before를 설정하는 일반적인 방법은 synchronized 블록 또는 volatile 변수에 쓰거나 읽는 것과 같이 이러한 작업을 synchronize으로하는 것입니다.

이러한 동기화가없는 경우 런타임은 스레드를 독립적으로 실행하므로 현재 스레드는 관찰 할 수 없습니다.

즉, 공유 상태가 변경 될 수 있다면 일반적으로 액세스 할 수있는 스레드를 동기화해야합니다.