2016-10-20 2 views
0

목록 3.15. 제대로 게시되지 않으면 실패 위험에 처한 클래스. javac의이 if (n != n)를 최적화하지 왜연습에서 책 자바 동시성의 예를 이해하는 방법?

public class Holder { 
private int n; 
public Holder(int n) { this.n = n; } 
public void assertSanity() { 
if (n != n) 
throw new AssertionError("This statement is false."); 
} 
} 

나의 첫번째 질문은?

다음은 예

public class TestSync { 
    private int n; 

    public TestSync(int n) { 
     this.n = n; 
    } 

    public void assertSanity() { 
     if(n!=n) 
      throw new AssertionError("This statement is false"); 
    } 

    private static TestSync test; 
    public static void main(String[] args) { 
     new Thread(new Runnable() { 
      @Override 
      public void run() { 
       while(true) { 
        if(test == null) test = new TestSync(2); 
        else test = null; 
       } 
      } 
     }).start(); 

     new Thread(new Runnable() { 
      @Override 
      public void run() { 
       while(true) { 
        if(test != null) 
         try { 
          test.assertSanity(); 
         } catch (NullPointerException e) { 

         } 
       } 
      } 
     }).start(); 
    } 
} 

내 데모입니다 그리고 내 두 번째 질문은 내가 옳은 일을 했습니까입니까? 데모를 실행할 때 예외가 발생하지 않기 때문입니다.

UPDATE 내 첫 번째 질문에 대한

1.Addition : 나는 if(false)-if(n!=n)을 최적화하고 축소 할 javac의를 thinked javap -c TestSync.class

public void assertSanity(); 
    Code: 
     0: aload_0 
     1: getfield  #3     // Field n:I 
     4: aload_0 
     5: getfield  #3     // Field n:I 
     8: if_icmpeq  21 
     11: new   #4     // class java/lang/AssertionError 
     14: dup 
     15: ldc   #5     // String This statement is false 
     17: invokespecial #6     // Method java/lang/AssertionError."<init>":(Ljava/lang/Object;)V 
     20: athrow 
     21: return 

.

2. 을 추가 한 이유는 if(test != null)입니까?

test 필드는 다른 스레드가 일 수 있다고 생각하므로 if(test!=null) 뒤에 있습니다.

+0

무엇이 질문입니까? javac이 그것을 최적화하지 않는다는 것을 어떻게 알 수 있습니까? null 객체에 대한 if 문 내부에서 NullPointerException에 대한 try catch가있는 이유는 무엇입니까? –

+0

@ cricket_007 이미 내 질문 업데이트 – dcnh35

+0

내가 틀릴 수도 있지만 '테스트'가 '동기화'되어야합니까? –

답변

0

우선, javac은 코드를 최적화하지 않으므로 컴파일 중입니다. 값이 인 컴파일 시간 상수 인 경우에만 컴파일 타임 상수를 형성하는 컴파일 타임에 표현식을 평가하려면 javac이 필요합니다 (JLS §15.28. Constant Expressions 참조).

그러나 작업은 런타임에 최적화되고 최적화 프로그램이 낙관적 인 가정을 사용할 수있게 해주는 스레드 동기화 측정 값이 없어도 두 변수 사이에서 변수가 변경되지 않습니다. 그래서 n!=n 표현으로 인해 reads¹ 사이의 짧은 시간에 어느 true로 평가의 낮은 확률로 시작하고 거의 걷어 최적화 후 true 수 없을 것입니다. 표현 n!=n 항상 false이 보장되지 않은 상태에서, 그것은 가능성이 그래서 실제로는 true이 될 것입니다. 물론

, 머피의 법칙에 따라 어쨌든 그 오류를 자극 할 때, 그것은하지만, 한 번 고객에 한 동안, 결코 일어나지 않을 것이다, 그러나 재현 ...

그 경우에도 두 번째 스레드를 참고하지 ¹ 결코 경합 조건으로 인해 초기 값 0을 읽었을 때, n!=n은 실패 할 것이고, 그 다음 읽기에서 초기 0을 다시 읽지 않으면 실패합니다.

+0

**으로 만들고 싶습니다. 따라서 n!= n 표현은 false로 평가 될 가능성이 적습니다. ** 'false'가 'true'여야합니다. – dcnh35

+0

맞습니다. 'n! = n'은 너무 부자연 스럽기 때문에 혼동하기 쉽습니다. – Holger

관련 문제