2009-10-25 4 views
6

몇 개의 스레드 읽기 (common concurrency problems, volatile keyword, memory model) Java의 동시성 문제에 대해 혼란스러워합니다.둘 이상의 스레드가 필드에 액세스 할 수 있으면 volatile로 표시해야합니까?

나는 하나 이상의 스레드가 액세스하는 많은 필드가 있습니다. 나는 그것들을 관통하고 모두 휘발성으로 표시해야합니까?

클래스를 만들 때 여러 스레드가 액세스 할 수 있는지 여부를 알지 못하기 때문에 모든 필드를 이 아닌이 휘발성이되도록하는 것이 안전하지 않으므로 사용하지 않을 경우는 거의 없습니다. . 이 올바른지?

제게 이것은 1.5 버전의 JVM과 관련이 있습니다 만, 제 설정에 대한 응답으로 제한되지는 않습니다.

답변

3

필드가 여러 스레드에서 액세스되는 경우 volatile 또는 final이거나 동기화 된 블록으로 만 액세스해야합니다. 그렇지 않으면 할당 된 값이 다른 스레드에 표시되지 않을 수 있습니다.

클래스는 다중 스레드에 의한 동시 액세스를 위해 특별히 설계되어야합니다. 휘발성 또는 최종 필드 만 표시하기 만하면 스레드 안전성이 충분하지 않습니다. 그래서

등 일관성 문제 (waitnotify를 사용하여 예를 들어), 스레드 간 신호에 대한 우려 (여러 필드에 대한 변경의 자성이)있다, 그것은 개체 만 볼 수 있어야한다고 가정하는 것이 가장 안전하다 단 하나의 쓰레드는 다르게 문서화되어 있지 않다. 모든 개체를 스레드로부터 안전하게 보호 할 필요는 없으며 소프트웨어 속도면에서 비용이 많이 드는 —이지만 개발 비용면에서 더 중요합니다.

대신 소프트웨어는 가능한 한 동시 스레드가 서로 상호 작용하도록 설계해야합니다. 상호 작용하는 지점을 명확하게 식별하여 적절한 동시성 제어를 설계 할 수 있어야합니다.

4

글쎄, 당신은 그 다른 질문을 읽었습니다 그리고 당신이 이미 답을 읽은 가정, 그래서 난 그냥 몇 가지 중요한 점을 강조합니다 :

  1. 들이 변경하려는를? 그렇지 않다면 휘발성이 필요하지 않습니다.
  2. 그렇다면 다른 필드와 관련된 값입니까? 그렇다면 포인트 4로 이동
  3. 얼마나 많은 스레드가 변경합니까? 1이면 1, 그 다음 휘발성이 모두 필요합니다.
  4. 2 번에 대한 대답이 "아니오"이거나 하나 이상의 스레드가 쓸 경우 이 충분하지 않으므로 일 경우 액세스를

추가를 동기화 : 필드 참조 객체가, 다음은 자신의 필드가되며 모든 고려 사항은 이러한 분야에 적용
합니다.

1

짧은 대답은 아니오입니다. 스레딩 문제는 이보다 더 생각하고 계획해야합니다. 휘발성이 스레딩에 도움이되는시기와 그렇지 않은 경우에 대한 제한 사항은 this을 참조하십시오. 값의 수정은 적절하게 동기화되어야하지만 매우 일반적으로 수정하려면 한 번에 둘 이상의 변수의 상태가 필요합니다. 예를 들어 변수가 있고 조건을 충족하는 경우 변수를 변경하려고한다고 가정 해보십시오. 배열로부터의 읽기와 배열에 대한 쓰기는 서로 다른 명령어이며 함께 동기화되어야합니다. 휘발성이 충분하지 않습니다.

변수가 가변 개체 (예 : 배열 또는 컬렉션)를 참조하고 해당 개체와 상호 작용하면 참조가 휘발성이기 때문에 스레드로부터 안전하지 않을 수도 있습니다.

2

자물쇠를 사용하십시오. volatile은 일부 경우 유용 할 수 있지만 올바르게 진행하기가 매우 어렵습니다. 예를 들어 두 개의 스레드가 동시에 Increment()를 실행하면 결과가 counter = 1을 할 수 있도록

class Foo { 
    private volatile int counter = 0; 
    int Increment() { 
    counter++; 
    return counter; 
    } 
} 

, 그것은 가능합니다. 이는 컴퓨터가 먼저 counter을 검색하고 추가 한 다음 다시 저장하기 때문입니다. 휘발성은 저장 및로드가 다른 명령문과 관련하여 특정 순서로 수행되도록합니다. 모두가 같은 모니터에 의해 보호되는 특정 필드에 액세스하는 경우, volatile이 필요하지 않을 것 - synchronized 보통 volatile에 대한 필요성이 미연에 방지하는 것이

참고.

volatile을 사용하면 잠금이없는 알고리즘을 만드는 것이 매우 어렵습니다. 이미 너무 느리다는 확실한 증거가없는 한 synchronized을 고수하고 구현하려는 알고리즘에 대한 자세한 분석을 수행해야합니다.

+0

이 특별한 사용 사례는 직접'synchronized'을 사용하는 대신 AtomicInteger를 참조하십시오. – erickson

+1

실제로. 필자는 맹목적으로 '동기'를 사용하여 정확히 무엇을 제공하고 제공하지 않는지 모르는 함정을 보여주고 싶었습니다. – bdonlan

관련 문제