2012-08-28 2 views
0

아래 코드가 threadsafe가 아닌 이유를 알려주십시오. 내가 얻는 출력은 0 또는 45 또는 90입니다. 공유 리소스 카운터에는 동기화 된 메서드가 있으므로 출력으로 항상 90을 기다리고 있습니다. 내가 여기서 뭔가를 놓치고 있니? 제발 조언. 친절하게도이 코드를 threadsafe로 만드는 방법을 알려주십시오.동기화 된 메서드가 스레드 안전하지 않음

class Counter{ 

    long count = 0; 

    public synchronized void add(long value){ 
     this.count += value; 
    } 
} 
class CounterThread extends Thread{ 

    protected Counter counter = null; 

    public CounterThread(Counter counter){ 
     this.counter = counter; 
    } 

    public void run() { 
    for(int i=0; i<10; i++){ 
      counter.add(i); 
     } 
    } 
} 
public class Example { 

    public static void main(String[] args){ 

    Counter counter = new Counter(); 
    Thread threadA = new CounterThread(counter); 
    Thread threadB = new CounterThread(counter); 

    threadA.start(); 
    threadB.start(); 

    System.out.println(counter.count); 
    } 
} 

답변

3

스레드가 중지 될 때까지 println을 기다리지 마십시오. 따라서 for-loops가 아직 처리중인 동안 카운터의 값을 출력합니다. thread-safety로 아무것도 할 필요는 없습니다.

+0

만약 내가 올바른 값을 읽을 수도 동기화되어야합니다 –

+0

왜? 당신은 간단한 긴 가치를 읽습니다. 그건 원자가가 될까요? – JohnB

+0

공개 여부 http://jeremymanson.blogspot.nl/2007/08/atomicity-visibility-and-ordering.html에 대해 알아보십시오. 어쩌면 내가 틀렸어 –

2

Counter 액세스가 threadsafe이지만 다른 스레드가 작업을 수행하기 전에 System.out.println(counter.count);이 발생할 수 있습니다.

0

3 개의 스레드가 실행 중입니다. 하나는 변수 threadA에 할당되고 하나는 threadB 및 메인 스레드에 할당됩니다.

main 메서드가 실행되는 동안 주 스레드가 실행됩니다. 나머지 2 개는 주 스레드와 동시에 시작되고 실행됩니다. 그러나 주 스레드는 다른 스레드가 완료 될 때까지 기다리지 못하도록 차단되지 않으므로 실행할 기회가있을 때 결과를 인쇄합니다.

+0

주 스레드를 자려고했는데 90 세로 출력이 나왔습니다. 여기에 스레드가 3 개 있다는 사실 때문에 혼란이 생겼습니다. – user1445850

1

코드는 스레드 안전하지만, 더 좋은 방법은 동기화 방법 제거하고 두 개의 스레드가 완료되기 전에 AtomicLong 및 사용 getAndAdd (긴) 방법

public final long getAndAdd(long delta) 
>Atomically add the given value to current value. 
6

기본적으로이 값을 읽는을 사용하여 얻을 그들의 실행.

join을 사용하면 스레드가 완료 될 때까지 기다릴 수 있습니다.

동기화 된 추가 메소드 대신 AtomicLongaddAndGet 메소드를 사용해보십시오.

12

스레드가 완료 될 때까지 기다립니다. 추가 결과를 인쇄하기 전에

threadA.join(); 
threadB.join(); 

을 인쇄하십시오.

+0

Wonderful, thx. 그거야. – user1445850