2016-10-06 2 views
5

스레드 안전하지 않으므로 SimpleDateFormat을 예로 들어 보겠습니다.volatile vs Java의 threadLocal

나는 각 스레드가 SimpleDateFormat에의 복사본이 같은 ThreadLocal를 사용하도록 허용 할 수 있습니다 :

private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){ 
    @Override 
    protected SimpleDateFormat initialValue() 
    { 
     return new SimpleDateFormat("yyyyMMdd HHmm"); 
    } 
}; 

그러나 휘발성 키워드 보장 스레드 변수의 최신 복사본을 것입니다. 그래서 대신이 작업을 수행 할 수 있습니까?

volatile SimpleDateFormat myformatter; 

동일한 스레드 안전성을 얻을 수 있습니까?

+1

스레드 안전성 문제가 발생하지 않기 때문에 스레드 안전성 문제는 'SimpleDateFormat'이 참조가 휘발성 필드에 저장되어 있는지 여부와 관계없이 변경할 수있는 상태입니다. –

+1

스레드 로컬과 '휘발성'은 동일하지 않습니다! 스레드 로컬의 경우 각 스레드에 대한 변수의 별도 사본이 있습니다. '휘발성'으로 모든 스레드는 하나의 변수를 공유합니다. Andy가 언급했듯이,'SimpleDateFormat'은 다중 스레드에 의해 동시에 업데이트되어서는 안되는 내부 상태를 가지기 때문에 변수를 volatile로 설정하면 스레드로부터 안전하지 않습니다. – Jesper

답변

4

휘발성 키워드 보장 스레드 변수

휘발성 변수

아니라 그 분야의 최신 복사본을 것입니다.

또한 volatile은 변수 값을 변경해야하는 경우에만 유용합니다. 사용 사례에서, final이 더 적절할 것 같습니다

private static final SimpleDateFormat format = ... 

이 또한 변수의 가장 최근의 값을 갖게됩니다 보장 - 그것은 한 번만 값을 할당 할 수 있기 때문에, 그리고 static final는 보장이있다 클래스가 완전하게로드되면 가시성.


는하지만이 SimpleDateFormat 어쨌든 안전 스레드되지 않는 이유가되지 않습니다 : 그것은 날짜를 포맷 할 때 그 중간 값을 저장하는 데 사용하는 가변 상태를 가지고있다.

하나의 스레드가 format을 호출하고 다른 하나가 동일한 SimpleDateFormatter 인스턴스에 대해 format 메서드를 호출하는 경우 이러한 중간 변수가 예기치 않게 스톰되고 스레드 간의 간섭으로 이어져 예기치 않은 결과가 발생합니다.

중간 변수의 값이 다른 스레드에서 읽고 쓸 때 최신 값인지 여부는 중요하지 않습니다. 업데이트를 분산시킬 수 있습니다.

간단히 말해서 volatile은 스레드 간섭을 막지 않으므로 여기서 ThreadLocal에 대한 적절한 대안이 아닙니다.

+1

'휘발성 변수의 경우에만 해당 필드가 아닌 것입니다.'--- 실제로는 부정확하고 오해의 소지가 있습니다. 'volatile'필드에 쓰기 전에 쓰기 스레드가했던 참조 된 객체의 필드에 대한 모든 기록을 관찰 할 것이므로 . 이것은 안전한 출판의 본질입니다. –

+0

@MarkoTopolnik 정말요? 필자가 생각하는 것은'System.out.println (volatileField.nonVolatileField);와 같은 것입니다.'volatileField'를 읽으면 그 시점까지'nonVolatileField'에 대한 모든 쓰기를 볼 수 있습니다. 그러나'nonVolatileField'는'volatileField'와'volatileField.nonVolatileField'를 읽는 사이에 갱신 될 수 없습니까? –

+0

네, 그 이유는 말씨가 "오도 된"것이지 "틀린"것은 아닙니다. '휘발성 '참조 자체를 제외하고는 _any_ 보장을받지 못하는 것 같습니다. 반면에, "가장 최근"는 JMM의 잘 정의 된 개념조차 아니기 때문에 "가장 최근"상태의 "휘발성"필드를 관찰 할 수 있습니다. 근본적인 차이점은 순차적 일관성 대 선형성의 차이입니다. –

0

SimpleDateFormat의 동일한 인스턴스가 다른 스레드에서 사용되므로 volatile과 동일한 스레드 안전성을 얻지 못합니다.

1

ThreadLocal은 스레드가 개체의 로컬 복사본을 가질 수있게 해주는 기능입니다. ThreadLocals는 스레드 안전 정책 스레드 제한 내에서 스레드 안전성이있는 객체와 함께 사용하는 것이 가장 좋습니다 ("스레드 안전"이 아닌 많은 객체의 경우에도 해당 스레드에 대한 참조가 누출되지 않는 한 스레드 안전 사용은 여전히 ​​가능합니다. 제한 스레드). ThreadLocals는 인스턴스를 생성하는 스레드 외부에서 공유되는 변경 가능한 객체의 스레드 안전 사용에 도움이 될 수 없습니다.

volatile 키워드는 다양한 스레드에서 액세스 할 수있는 변수로 약한 형태의 스레드 안전성을 제공하는 데 사용됩니다.중요한 차이점은 ThreadLocals는 둘 이상의 스레드가 액세스하지 않는 것이 가장 일반적이라는 것입니다.

스레드 안전성은 가시성 (변수에 대한 최신 업데이트가 다른 스레드에 표시되어야 함)과 상호 배제 (상태가 일관성이없는 것으로 관찰 될 수 있도록 원자 상태이어야 함)를 필요로합니다. Volatile은 Java 메모리 모델과 함께 작동하여 변수가 표시 될 수 있지만 상호 배제의 형식을 제공하지 않으므로 객체의 상태 전이에 원 자성을 제공하지 않습니다.

volatileThreadLocal이 너무 다르기 때문에 다른 것을 대체 할 수있는 일반적인 상황이 없습니다.