2010-12-16 5 views
0

다음 코드는 올바른 균형 (100)을 인쇄해서는 안되지만 매번 100을 인쇄합니다. 왜 그런가요? 다음 코드는 스레드로부터 안전하지는 않습니다.자바 쓰레딩 질문

public class ThreadObject implements Runnable{ 

    private int balance; 

    public ThreadObject() { 
     super(); 
    } 

    public void add() { 
     int i = balance; 
     balance = i + 1; 
    } 

    public void run() {  
     for(int i=0;i<50;i++) { 
      add(); 
      System.out.println("balance is " + balance); 
     } 
    } 

} 

public class ThreadMain { 

    public static void main(String[] args) { 

     ThreadObject to1 = new ThreadObject(); 
     Thread t1 = new Thread(to1); 
     Thread t2 = new Thread(to1); 
     t1.start(); 
     t2.start(); 

    } 
} 

다음 코드가 실제로 스레드로부터 안전하면 어떻게 설명 할 수 있습니까?

add()의 코드가 스레드로부터 안전하지 않은 것처럼 보입니다. 하나의 스레드가 현재 balancei을 설정하고있을 수 있지만 두 번째 스레드가 인계되어 balance을 업데이트하는 동안 비활성 상태가됩니다. 그런 다음 스레드가 깨어나서 balance을 더 이상 사용되지 않는 i에 1을 설정합니다.

답변

1

println은 저울을 업데이트하는 코드보다 수천 배 정도 느립니다. 각 스레드는 거의 모든 시간 인쇄에 소비하므로 균형을 동시에 업데이트 할 가능성은 매우 적습니다.

i을 읽고 i + 1을 쓰는 사이에 작은 수면을 추가하십시오.

위의 코드를 실행 한 후 가장 작은 가능한 값은 i입니다.

+0

이 최소값 50입니까? 내가 생각할 수있는 최악의 경우는 T1이 잠자기 상태가되기 때문에 T2가 처리하고 업데이트하고 T1이 깨어나고 균형이 업데이트되고 T2가 깨어나 균형을 업데이트하기 때문에이 패턴이 계속됩니다. 또는 그보다 더 나쁜 경우가 있습니까? – Glide

+0

@ 글라이드 : 아니, 훨씬 적습니다. –

+0

나는 알아낼 수 없다. 설명해 주시겠습니까? – Glide

0

인쇄면이 약간 위쪽을 이동하면 스레드로부터 안전하지 않은지 알 수 있습니다. 여전히 변경 사항이 표시되지 않으면 5000을 더 크게하십시오 (5000 이상).

public void add() { 
    int i = balance; 
    System.out.println("balance is " + balance); 
    balance = i + 1; 
} 

public void run() {  
    for(int i=0;i<50;i++) { 
     add(); 
    } 
}