2013-05-02 4 views
2

이 코드 발견 this question을 검토하는 동안 : 이해가 안하지만 왜이 실패왜이 코드가 실패 할 수 있습니까?

class MyThread extends Thread { 
    private boolean stop = false; 

    public void run() { 
    while(!stop) { 
     doSomeWork(); 
    } 
    } 

    public void setStop() { 
    this.stop = true; 
    } 
} 

합니다. 다른 스레드가 "실제"정지 변수에 액세스하지 못합니까?

+0

에서 언급 한 바와 같이? MyThread의 동일한 인스턴스 또는 다른 인스턴스에서? –

+0

불행히도이 질문에 대한 추상적 인 예는 –

+0

입니다. setStop은 다른 스레드에서 호출 될 것입니다. 모든 실행 방법은 멈추기 위해해야만합니다. 반환 만하면 플래그가 필요 없습니다. –

답변

5

휘발성 할 필요가 stop 인스턴스 변수는, 그렇지 않으면 다른 스레드가 변경 사항을 볼 수 있습니다 보장이 없습니다. 많은 상충되는 관심사가 있습니다 : 스레드는 프로그램 상태의 일관된 뷰를 원하고 CPU는 데이터를 캐시 할 수 있기를 원하며 JVM은 명령을 재주문 할 수 있기를 원합니다. 인스턴스 변수를 volatile로 만들면 명령 순서 재 지정을 제한하는 관계가 설정되기 전에 캐싱 할 수없고 그럴 수 있습니다.

변수 휘발성를 표시하지 않고 발생할 수 있습니다 무엇을 재정렬의 좋은 예를 들어 this other answer (+1)를 참조하십시오. (. using interruption for thread cancellation는 인스턴스 변수를 사용하는 것이 바람직하다 그런데)

+0

이것이 실패 할 수있는 # 1 이유 인 hoisting에 대해 언급해야합니다. –

+0

@ 존 빈트 "호이 스팅"? – user2246674

+1

@ user2246674 나는 호이스트 처리에 대한 내 대답을 만들었습니다. –

0

다른 스레드가 정지 업데이트 된 값을 볼 수 보장되지 않습니다 - 당신이 관계를 "전에 발생"설정해야합니다. 가장 간단한 방법은 정지를 휘발성으로 만드는 것입니다.

1

변수 stop은 volatile로 선언되어야합니다.

내가 스레드를 중지 인터럽트를 사용하여 선호하지만

.

6

JIT 컴파일러는 순서를 다시 수행 할 수 있습니다 읽고 너무 오래 작업을 순차적으로 일관하고

  • 변경된 행동이 내 스레드 의미를 위반하지
    1. 같은 응용 프로그램에 기록합니다.

    이것은 단지 하나의 스레드에 의해 실행되는 것처럼 모든 동작이 동일한 방식으로 나타나야한다는 멋진 말입니다. 그래서 당신은 JIT이

    class MyThread extends Thread { 
        private boolean stop = false; 
    
        public void run() { 
        if(!stop){ 
         while(true){ 
    
         } 
        } 
        } 
    

    이처럼 보이도록 코드를 다시 컴파일 얻을 수있는 것은 리프팅 라는 법적 최적화입니다. 시리얼과 똑같은 기능을하지만 여러 스레드를 사용할 때 놀라운 결과를 제공합니다. 당신이 어떤 재 순서화를 실행하지 않는 자바를 말하고있다 휘발성 필드를 선언함으로써

    . 당신은`setStop()`를 호출하는 방법 메모리 일관성과 함께 나단 휴즈

  • +0

    JVM은 호이스트하기 전에'doSomeWork()'가'stop' 필드를 설정했는지 확인합니까? 그렇지 않으면 최적화가 그렇게 최적이 아닌 것 같아서 그렇습니다. :) – dlev

    +0

    @dlev 예, 절대적으로! 그렇지 않으면 끔찍한 최적화가됩니다. –

    +1

    좋은 정보, 감사합니다! –