말은, 나는 데이터 객체를 가지고도스레드 풀, 공유 데이터, 자바 동기화
Collection<ValueRef> masterList = ...;
내가 : 각 데이터 객체가 마스터 콜렉션에 저장됩니다
class ValueRef { double value; }
각 작업에는 데이터 개체의 로컬 컬렉션이 있습니다 (각 데이터 개체는 masterList
에 표시됨) :
class Job implements Runnable {
Collection<ValueRef> neededValues = ...;
void run() {
double sum = 0;
for (ValueRef x: neededValues) sum += x;
System.out.println(sum);
}
}
사용의 경우는 :
for (ValueRef x: masterList) { x.value = Math.random(); }
일부 작업과 작업 큐를 채 웁니다.
일어나 각 작업이
참고 평가 될 때까지 스레드 풀
기다립니다 : 작업 평가하는 동안, 모든 값은 모두 일정하다. 그러나 스레드는 과거에 작업을 평가했을 가능성이 있으며 캐시 된 값을 유지합니다.
질문 : 각 스레드가 최신 값을 확인하는 데 필요한 최소한의 동기화 양은 얼마입니까?
모니터/잠금 관점에서 동기화하는 것을 이해합니다. 캐시/플러시 관점 (즉, 동기화 된 블록의 입/출력시 메모리 모델에서 보장되는 내용)에서 동기화하는 것을 이해하지 못합니다.
내게는 새 값을 주 메모리에 커밋하기 위해 값을 업데이트하는 스레드에서 한 번 동기화하고 작업자 스레드 당 한 번 캐시를 플러시하여 새 값을 읽을 필요가 있다고 느낍니다. 그러나 나는 이것이 최선의 방법인지 확신 할 수 없다.
내 방식 : 글로벌 모니터를 만들 : static Object guard = new Object();
을 그리고, guard
에 동기화, 마스터 목록을 업데이트하는 동안. 그런 다음 스레드 풀을 시작하기 전에 풀의 각 스레드에 대해 한 번 빈 블록의 guard
에 동기화하십시오.
실제로 해당 스레드에서 읽는 값을 모두 플러시 할 수 있습니까? 또는 동기화 블록 내에서 만진 값은 무엇입니까? 어떤 경우에는 빈 블록 대신 루프에서 각 값을 한 번 읽어야합니다.
감사합니다.
편집 : 제 생각에는 동기화 된 블록을 종료하면 모든 첫 번째 읽기 (그 시점 이후)가 주 메모리로 이동합니까? 내가 무엇을 동기화했는지에 관계없이?
휘발성 키워드 – ControlAltDel
을 사용하기에 거의 완벽한 장소처럼 보입니다. 나는 (사실 상수) 한 번 쓰지만 잠재적으로 수백만 번 읽는 중입니다. 휘발성은 결코 로컬에 캐시되지 않습니다. 매번 스레드 풀을 만든 경우 코드는 괜찮은 승/O 동기화/휘발성 (이전 캐시가 존재하지 않으므로)으로 작동합니다. –
나는 여기 휘발성에 대한 필요성을 보지 못했다. ValueRef가 효과적으로 불변 인 경우 실제로 불변으로 만듭니다. Double을 사용하십시오. 작업이 예정되기 전에 각 작업에 대한 새로운 콜렉션을 작성하고이를 (미리 알림으로서) unmodifiableCollection에 랩핑하십시오. 무슨 문제를 생각하니? –