2010-04-05 2 views
41

Java 메모리 모델에서는 int을 쓰는 것이 필수적이라고 규정합니다. 즉, 한 스레드에서 값을 쓰고 다른 스레드에서 값을 읽으면 모든 바이트 또는 하나도 가져 오지는 않지만 결코 새로운 바이트 2 개와 오래된 바이트 2 개를 얻지는 않습니다.64 비트 VM에서 참조 원자를 쓰는 중입니다

long에 대한 보장이 없습니다. 여기서 을 변수 0에 저장하기 전에 쓰면 다른 스레드가 0x112233440000000 또는 0x0000000055667788이 될 수 있습니다.

이제 사양에서는 개체 참조를 int 또는 long으로 지정하지 않습니다. 타입 안전성을 위해, 나는 그들이 원자 적으로 쓰여질 수 있다고 확신하지만, 64 비트 VM에서 이러한 참조는 64 비트 값 (단순히 메모리 주소) 일 수있다.

지금 여기 내 질문은 :

  • 이가 (내가 발견하지 않았 음) 포함하는 모든 메모리 모델 사양이 있습니까?
  • 64 비트 VM에서 장기간 쓰기가 의심 스럽습니까?
  • VM이 32 비트 참조를 매핑해야합니까?

감사합니다, 스테 펜

+2

@Steffen 하일 : 하찮은 일에 속 태우고가 아닌 모든 참조 (의한 64 비트 참조 발생되는 폐기물의 굉장한 양)에도 64 비트 VM에 내부적으로 64 비트 참고.현대의 VM은 * "CompressedOops"*라고하는 포인터 압축/참조 압축을 사용하고 있습니다. : http://wikis.sun.com/display/HotSpotInternals/CompressedOops 그래서 64 비트 값이 될 수는 있지만 그럴 수는 없습니다. 더크가 게시 한 답변에 많은 변화가있는 것은 아닙니다. – SyntaxT3rr0r

답변

52

자바 프로그래밍 언어 메모리 모델의 목적 JLS section 17.7: Non-atomic Treatment of double and long

를 참조하십시오, 비 휘발성 긴 또는 double 값에 단일 쓰기는 두 가지로 처리됩니다 별도 쓰기 : 각 32 비트 절반에 하나. 이로 인해 스레드가 에서 64 비트 값의 처음 32 비트를 하나의 쓰기로보고 다른 두 번째 비트를 다른 쓰기로 보는 상황이 발생할 수 있습니다.

휘발성 long 및 double 값의 쓰기 및 읽기는 항상 원자 적입니다.

참조의 쓰기 및 읽기는 항상 에 관계없이 32 비트 또는 64 비트 값으로 구현됩니다.

구현에 편리 인접하는 32- 비트 값의 두 기록 동작으로 64 비트 길이 또는 큰 값의 단일 기입 동작을 분할 찾을 수있다. 효율성을 위해이 동작은 구현에 따라 다릅니다. Java 가상 머신 의 구현은 long 및 double 값의 쓰기를 원자 적으로 또는 의 두 부분으로 자유롭게 수행 할 수 있습니다.

가능하면 Java 가상 머신을 구현하여 을 64 비트 값으로 분할하지 않는 것이 좋습니다. 프로그래머는 에 공유 64 비트 값을 volatile로 선언하거나 가능한 복잡성을 피하기 위해 해당 프로그램 을 올바르게 동기화하는 것이 좋습니다.

(강조 추가)

+0

그래, 스펙의 요점을 다시 놓쳤다. 나는 너무 피곤해서 질문하는 대신 잠자야한다. 포인터를 가져 주셔서 감사합니다. (AGAIN) –

+1

"32 비트 또는 64 비트 값으로 구현되는지 여부에 관계없이"참조에 대한 쓰기 및 읽기는 항상 원 자성입니다. "라는 이유로 AtomicReference 클래스 (https://docs.oracle.com/javase/)가있는 이유는 무엇입니까? 7/docs/api/java/util/동시/원자/AtomicReference.html)? 메소드 때문에 getAndSet/compareAndSet? –

+0

찢어진 참조 값을 볼 수없는 것은 그림의 일부일뿐입니다. 'AtomicReference'는 주로 동기화 API (당신이 언급 한'compareAndSet'), @ mc.android.developer에 존재합니다. 그리고 여기에는 "유일한"것은 없습니다. 그것은 실제로 중요한 부분입니다. – Dirk