2017-11-19 4 views
0

나는 동시 프로그래밍의 초보자이며, 내가 왜 sleep(1)에 에 댓글을 달았을 때이 프로그램이 끝나지 않는지 정확히 이해하고 싶습니다.) Main 스레드로 손을 돌려 준다. 아마도 Busy waiting과 관련이있을 것이다.동시 프로그래밍, 스레드간에 값 공유

public class Rdv<V> { 
    private V value; 

    public void set(V value) { 
    Objects.requireNonNull(value); 
    this.value = value; 
    } 

    public V get() throws InterruptedException { 
    while(value == null) { 
     Thread.sleep(1); // then comment this line ! 
    } 
    return value; 
    } 

    public static void main(String[] args) throws InterruptedException { 
    Rdv<String> rendezVous = new Rdv<>(); 
    new Thread(() -> { 
     try { 
     Thread.sleep(5000); 
     } catch (InterruptedException e) { 
     throw new AssertionError(e); 
     } 
     rendezVous.set("hello"); 
    }).start(); 

    System.out.println(rendezVous.get()); 
    } 
} 
+0

관련 : https://stackoverflow.com/questions/42676751/thread-sleep-makes-compiler-read-value-every-time – shmosel

답변

2

우선이 프로그램은 심각하게 손상되었습니다. 수면 상태에서도 종료된다는 보장은 없습니다. 그것은 가능할 수도 있지만 그렇지 않을 수도 있습니다.

값 필드가 휘발성이 아니므로 값을 가져 오거나 설정할 때 동기화 또는 다른 잠금을 사용하지 않아야합니다. 즉, 한 스레드가 다른 스레드가 변경되는 것을 볼 수 있다는 보장이 없음을 의미합니다! 프로그램을 멈추기로되어있는 값에 대한 쓰기는 대기중인 스레드에서 결코 볼 수 없습니다. Java가 해석 모드로 실행되기 때문에 정상적으로 작동하는 것은 정상적으로 작동합니다. 수면 시간이없는 컴파일러는 잠자기 시간없이 코드를 최적화 할 시간이있었습니다. while 루프는 동일한 작업을 수행하는 훨씬 효율적인 버전으로 다시 작성 될 수 있습니다. 그래서 그것은 그것이하는 일입니다.

가장 쉬운 해결 방법은 값 필드를 volatile로 선언하는 것입니다. 그런 다음 Java는 변경 될 수 있으며 읽기 최적화를 피할 수 있음을 알고 있습니다.

Java 메모리 모델을 잘 모르는 경우 짧은 버전은 항상 스레드간에 공유되는 데이터에 대한 액세스를 동기화합니다. 죄송합니다보다 더 안전!

+0

감사합니다. 물론이 프로그램은 전혀 안전하지 않지만, 컴파일러와 VM에서 일어나는 일을 이해하는 이상한 예 – Unconnu