2017-02-08 8 views
4

이전에 답변을 받았을 수 있지만 문제가 복잡하기 때문에 확인이 필요합니다. 그래서 질문을 바꿉니다Java에서 동기화 된 키워드의 메모리 효과

질문 1 : 스레드가 동기화 된 블록에 들어갈 때 메모리 바리어는 내가 동기화 한 객체의 필드뿐만 아니라 어떤 필드도 포함하게됩니까? 많은 객체가 동기화 된 블록 내에서 수정되면 스레드 메모리 캐시간에 많은 양의 메모리 이동이 발생합니다.

Thread 1 
object.field1 = ""; 
synchronized (lock) { 
    farAwayObject.field1 = ""; 
    farAwayObject.evenFarther.field2 = ""; 
} 

Thread 2. assuming thread ordering is correct 
synchronized (lock) { 
    //thread 2 guaranteed to see all fields above as "" 
    //even object.field1 ? 
} 

질문 2 :되는 일이-전에 관계의 스레드에서 object.field1 = ""; 1 개 암시 적 부분?

희망이 있지만 그렇지 않을 수도 있습니다. 동기화 블록에 넣지 않고 그렇게 만들 수있는 트릭이 없다면? 프로그램에서 추론하기가 어렵습니다. 그리고 모든 것을 동기화 된 {} 아래에 두는 것은 실용적이지 않습니다.

EDIT : 설명 : object.field1은 휘발성이 아니며 질문은 "스레드 2가 최소한 스레드 1의 쓰기를 보장합니다."라는 질문입니다. 내 질문은 메모리 가시성에 관한 것입니다. 논증을 위해서 쓰레드 1 만 비 휘발성 object.field1에 쓰는다고 가정 해 봅시다.

고쳐 될 수있다이 문제

"윌 같은 잠금 장치에 동기화 다른 스레드에 의해 볼 수 전에 만든 잠금 푸시 변화에 동기화 된 블록?"

+0

대답은 두 질문에 모두 예입니다. – shmosel

+0

@shmosel'object.field1'은 happen-before의 일부가 아니며'Thread2'가 업데이트를 보거나 보지 않을 수도 있다는 것을 이해했습니다. – CKing

답변

3

때 스레드는 메모리 배리어 모든 필드는, 터치가 I

에 동기화 객체 아니라 필드 동기 블록을 포함 진입

farAwayObjectevenFarther의 분야는 항상 수정 및 모든 응용 프로그램의 주위에 동일한 개체에 lock를 얻기에 의해 accesed되는 것을 가정하면, 모든 스레드가 항상 synchronized 이후 farAwayObjectevenFarther로 만든 업데이트를 볼 것 이 발생-이전 조건을 적용합니다. //thread 2 guaranteed to see all fields above as ""

같은

은이 선언하는 방법을 모른 채 object.field1라고 할 수 없습니다. field1volatile으로 표시되지 않은 참조 인 경우 의 일부가 아니며 관계 이전에 발생하고 스레드에 부실 값이 표시 될 수 있습니다.

아니겠습니까? 그렇지 않다면 동기화 블록에 넣지 않고 을 그렇게 만드는 트릭이 있습니까?

예. object.field1volatile으로 표시하십시오.

2

로 다시 표현 될 수있는 질문은 "전에 만든 잠금 푸시 변화에 동기화 된 블록 는 동기를 다른 스레드에 의해 볼 수 있을까요 :


당신의 편집 Addresing 같은 잠금 장치입니까? "

AFAIK 대답은 예입니다. 필기 스레드가 딩 스레드. 죄송 합니다만 이것은 일반적으로 보장 할 수없는 내용이므로 object.field1volatile으로 표시해야하고 명세서를 synchronized 블록 내로 옮겨야합니다.

캐시는 메인 메모리에 플러시 것에 대해 이야기 JSR 133를 살펴 보자 때 스레드 종료 syncronized 블록. 이것은 일을 더 분명히해야합니다.


+0

내 clarifaction을 참조하십시오. 나는 object.field1을 휘발성으로 설정하고 싶지 않다. synchronized (lock)이 실행될 때 주 메모리에 push 된 object.field1에 대한 thread1의 특정 쓰기가 아닌가? 없다면. 그러면 동기화 된 잠금 아래에서 JVM이 메모리 변경을 플래그합니다. 그 변화만을 밀어 붙이기 위해서? – Mordan

+0

@Mordan 편집보기 참조. 그게 일을 더 분명하게합니까? 추가 설명이 필요하면 알려주세요. – CKing

+0

귀하의 링크가 제 질문에 분명히 대답했습니다. 그렇습니다. 기분이 나아졌다. :) 나는 몇 주 동안 웹을 검색해 왔지만 그것을 찾지 못했습니다. 좋은 링크! 고맙습니다. – Mordan

3

1) 스레드 동기화 블록을 입력하면, 상기 메모리 배리어는 어느 필드가 포함되지 터치 I가 동기화 객체 단지 필드?

수정. (스레드 1과 스레드 2가 같은 잠금 장치에서 동기화된다고 가정하십시오.)

동기화 된 블록 내에서 많은 오브젝트가 수정되면 스레드 메모리 캐시간에 많은 양의 메모리 이동이 발생합니다.

잠재적으로 가능합니다. 그러나 캐시 사이에는 (아마도) 움직임이 없습니다. 한 프로세서의 캐시에서 메모리로, 그리고 메모리에서 두 번째 프로세서의 캐시로의 이동 일 가능성이 큽니다. 물론 하드웨어가 메모리 계층 구조를 구현하는 방법에 따라 다릅니다.

2) object.field1 = ""; 스레드 1에서 암시 적으로 happen-before 관계의 일부입니까?

발생-전에 관계

  1. 잠금을 획득하기 전에 object.field1에 쓰기 발생의 체인이있다.
  2. farAwayObject 등으로 쓰기 전에 발생합니다. 로크 전에 발생
  3. 는 락이 스레드 2 object.field1를 읽기 전에 발생 실 2
  4. 의해 취득되기 전에 발생 스레드 1
  5. 의해 해제된다.

문제는 lock가 스레드 1에 인수되기 전에, 또는 다른 스레드에 의해 하나, object.field1에 개입 쓰기가있는 경우 발생하는 것입니다. 두 경우 모두, 스레드 2가 스레드 1에 의해 쓰여진 값을 볼 수 있도록하기 위해선 발생 전 체인만으로는 충분하지 않습니다.

+0

내 설명에 비추어 명확히 할 수 있습니까? 중간에 쓰기가 없다고 가정하십시오. shmosel처럼 대답 할 수 있겠습니까? – Mordan

1

메모리 장벽에는 동기화 된 개체의 필드뿐만 아니라 모든 필드가 포함됩니다.

예.

is object.field1 = ""; 스레드 1에서 암시 적으로 happen-before 관계의 일부입니까?

예, 휘발성이 아니어도됩니다.


(가) - 일어나기 전에 주문 부분 위해서이다.

우연히 발생하는 순서는 에지 및 프로그램 순서와 동기화의 전이 폐쇄에 의해 부여됩니다. 유효한 부분 순서 : 반사, 전이 및 반 대칭이어야합니다.

(JLS 17.4.7) 동기화 에지 전에

조치 (즉, 동기화 된 잠금 해제)은 프로그램 순서로 정렬되므로 릴리스 동기화. 능동성은 에 의해 주문 된 동작이 다른 스레드에서 동일한 잠금의을 획득하므로 해당 잠금의 해제와 해당 잠금 해제 이전의 동작 모두와 함께 발생하기 전에 순서가 있음을 나타냅니다. 본문은 synchronized 블록입니다. 이것에 대해 기억해야 할 중요한 점은 synchronized 키워드의 대괄호와 같은 블록이 아니라 액션 (즉, 잠금 획득/해제)에서 정렬이 발생한다는 것입니다. 괄호는 수집/해제 작업의 위치와 일련의 작업을 인터리브 할 수없는 위치를 나타냅니다.

마지막으로 happen-before는 "부분적인"순서임을 기억하십시오. 그것은 의미

  1. 조치를 특정 순서로 와서 일 때 전에 메모리 일관성을 적용됩니까 (즉 릴리스/읽기/등을 작성, 취득) 이전 등 생산 프로그램 순서로 강한 보증에 따라
  2. 발생 올바른 기능.
  3. 이전에 발생하여 비 원자 작업의 인터리브에서 오는 오류를 방지하지 못함
  4. 이전에 발생하는 동작과 강력한 동작 간의 전이 관계입니다. (쓰기가 블록 앞에오고 블록 뒤에 읽기가있는 한 공유 변수의 값을 synchronized 블록 외부에 놓을 수 있습니다. 보다 강력한 주문 보증은 주문하기 전에 수행되지만 사양에 설명 된 추가 효과를 제공합니다.