2014-10-21 9 views
2

안녕하세요 모두 0에서 99까지의 숫자의 합계를 계산하는 간단한 프로그램을하고 있습니다. 나는 자바 스레드를 읽고 있었고, 특히 멀티 쓰레딩이 어떻게 작동하는지 이해하려고 노력했습니다. 개념을 이해하는 간단한 프로그램. 하지만 내 프로그램의 출력은 0과 4950을 출력하는 것과 다르다. 실행중인 스레드가 2 개있는 것 같니? 주 스레드 및 다음 개체 스레드가? 출력이 동기화되지 않았기 때문에 문제가 발생합니다. 나는 옳은 길을 가기를 바랍니다. 그러나 확실한 지침이 필요하지 않습니다. 누군가이 문제를 해결하기 위해 동기화 된 방법을 설명해 주시겠습니까? 그것을 이해하는 데 문제가 있습니까?문제는 자바에서 동기화 된 이해

public class Testing { 
    public static void main(String[] args) { 
     ThreadB b = new ThreadB(); 
     Thread a = new Thread(b); 
     a.start(); 
     System.out.println(b.total); 
    } 
}  

class ThreadB extends Thread { 
    int total; 

    public ThreadB() { 
     this.total = 0; 
    } 

    public synchronized int total() { 
     for(int i = 0; i < 100; i++) { 
      total += i; 
     } 
     return total; 
    } 

    public void run() { 
     System.out.println(total()); 
    } 
} 

답변

1

메인 스레드와 'a'스레드가 있습니다. 스레드에서 상속하지만 int로 처리하는 다른 개체 b가 있습니다.

합계를 수행하는 스레드 a를 실행하고 그 결과를 인쇄합니다. 그런 다음 저장된 b의 값을 인쇄합니다.

스레드가 동일한 변수를 공유하지 않으므로 동기화에 문제가 없습니다. 총계는 a와 b 사이에서 구분됩니다. 문제를 만들고 싶다면 int를 Testing의 구성원으로 만드십시오.

+0

그래서 개체 b는 주 스레드에서 상속됩니다. 스레드가 실행되고 합계를 수행합니다. 하지만 어떻게 스레드가 또한 결과를 인쇄 할 수 있습니다. 스레드가 그냥 0 및 4950 않습니다 인쇄하는 것 같습니다. 그래서 내 질문에 두 스레드가 동일한 결과를 생성 할 또는 다른 단어를 동일한 변수를 공유 할 수 있습니다. – user3497437

+0

Total을 Testing의 구성원으로 이동하십시오. 그런 다음 정수가 하나만 있으면 공유해야합니다. – mattm

0

동기화는 두 개 이상의 스레드가 동일한 리소스에 액세스하려고하고 있고 동시에 수행하지 않도록하려는 경우에 필요합니다. 이것은 쓰기 관점에서 보면 대개 중요합니다. 그러나 읽기 (예 : 여러 스레드가 동시에 값을 읽을 수 있고 동시에 업데이트하지 않고 여러 스레드가 동일한 자원을 업데이트하지 않을 수도 있습니다 동시에).

예에서 실제로 실행중인 스레드는 하나뿐입니다. 그게 의도라고 의심하지 않습니다. 메인 스레드와 스레드 a이 있습니다. 아무 것도 변경하지 않고 코드를 재구성했는데 잘하면 더 명확 해집니다.

public class Testing { 
    public static void main(String[] args) { 
     ThreadB b = new ThreadB(); 
     System.out.println(b.total); 

     Thread a = new Thread(b); 
     a.start(); 
    } 
}  

주 스레드는 실제로 아무 것도하지 않습니다. 그냥 새로운 객체 b를 만들고 b.total을 출력합니다 (따라서 0 값을 얻습니다). 최소한 b.start()으로 전화해야합니다.

a.start()으로 전화하면 계산 스레드가 실행됩니다. 이 부분은 계산 합계를 인쇄하는 ThreadB() 객체에서 계산을 시작합니다.

동시성을 진정으로 테스트하려면 다중 스레드가 액세스하는 공유 리소스가 있어야합니다. 그러나 total은 전용 인스턴스 멤버이므로 스레드 a와 b는 서로 다른 인스턴스 total을 가지며 동기화 문제가 발생하지 않습니다. synchronized 문은 각 스레드가 자신의 total() 메서드라고 부르기 때문에 불필요합니다.

http://www.tutorialspoint.com/java/java_thread_synchronization.htm에는 동기화 및 멀티 스레딩에 대한 좋은 설명/예가 있습니다.

0

여기에 단 두 개의 스레드 만 있습니다. main 메소드를 실행하는 데 사용되는 JVM에서 제공하는 스레드가 있습니다. 그런 다음 Thread 객체를 참조하는 a이라는 로컬 변수가 있습니다. 로컬 변수 b은 스레드를 참조하지만 스레드가 호출되지 않았기 때문에 스레드로 사용되지 않습니다. 모든 스레드는 Runnable을 구현하고 b을 스레드 a의 생성자에 전달하면 ba에 의해 실행 가능 파일로 사용됩니다.따라서 스레드 a이 실행되고 b에 정의 된 run 메소드가 실행됩니다.

ab 실행 메소드를 실행하면 b의 잠금이 계속됩니다. 프로그램에있는 다른 사람이 b에 자물쇠를 얻으려고하지 않습니다. 총계()에 대한 synchronized 키워드는 total() 메소드를 호출하는 스레드에만 영향을 주므로 주 메소드가 total이라는 b이라는 인스턴스 구성원에 액세스하지 못하도록하는 것은 없습니다. 따라서 메인 메서드는 계속 진행되며 스레드 a이 여전히 시작되기 때문에이 시점에서 업데이트되지 않은 total에 액세스합니다.

당신이 개인 총했고,이 같은 ThreadB에 접근을 추가 한 경우 :

public synchronized int getTotal() { return total;} 

여기에 동기화 의미하기 때문에 사용 "(잠금을 획득 할 인스턴스를 호출을 강제이 게터를 호출하는이 방법 잠금 "으로 호출되므로 total 값에 액세스하기 전에 total() 메서드와 새 getTotal() 메서드가 동일한 잠금을 공유합니다. 그런 다음 스레드 a이 실행 메소드에 들어가면 b에 대한 잠금을 획득하게되고 주 스레드는 전체에 액세스하기 위해 b에 대한 잠금을 확보 할 수있을 때까지 대기해야합니다.

그래도 그렇게해도 주 스레드는 b에 액세스 할 수 있으며 스레드 a이 시작되어 b에서 잠금을 획득 할 수 있기 전에 잠금을 획득 할 수 있습니다. 주 스레드와 스레드 a 사이에는 경쟁 조건이 있으며 주 스레드는 이미 시작되어 활성화되어 있으므로 (starting a new thread is expensive) 이점이 있습니다. b 스레드가 잠금을 먼저 획득 할 수 있도록 합계를 얻기 전에 주 메서드에 Thread.sleep을 추가 할 수 있습니다.