2011-09-27 5 views
1

두 개의 스레드가 동일한 메모리 주소를 공유하는 경우 (하나의 스레드가 n 번 증가하고 하나의 스레드가 n 번 감소하는 경우) 0 이외의 최종 결과를 얻을 수 있다는 것을 보여주는 유사한 C# 프로그램이 있습니다. n이 적당히 크면, C#에서 [-n, n] 사이에 0이 아닌 값을 표시하는 것이 매우 쉽습니다. 그러나 스레드 수를 1000 (500 up, 500 down)으로 늘리는 경우에도 Java가 0이 아닌 결과를 생성하도록 할 수는 없습니다. 거기에 일부 메모리 모델 또는 사양 차이 wrt C#을 나는이 프로그램이 항상 스케줄링이나 코어의 수를 인식하지 못하는에도 불구하고 0을 보장한다는 것을 인식하지 못 하겠어? 우리가 실험적으로 증명할 수 없다하더라도이 프로그램이 0이 아닌 가치를 만들어 낼 수 있다는 데 동의합니까? 이 Java 프로그램이 제로 이외의 값을 인쇄 할 수 있습니까?

은 (하지 :, 나는 here 이상이 정확한 질문을 찾았지만, 내가 그 항목의 코드를 실행하면 나는 또한 제로를 얻을.)

public class Counter 
{ 
    private int _counter = 0; 

    Counter() throws Exception 
    { 
    final int limit = Integer.MAX_VALUE; 

    Thread add = new Thread() 
    { 
     public void run() 
     { 
     for(int i = 0; i<limit; i++) 
     { 
      _counter++; 
     } 
     } 
    }; 

    Thread sub = new Thread() 
    { 
     public void run() 
     { 
     for(int i = 0; i<limit; i++) 
     { 
     _counter--; 
     } 
     } 
    }; 

    add.run(); 
    sub.run(); 
    add.join(); 
    sub.join(); 

    System.out.println(_counter); 
    } 

    public static void main(String[] args) throws Exception 
    { 
    new Counter(); 
    } 
} 
+3

난 당신이()'대신 실행'의 시작'호출 의미 추측()', 그렇지 않으면 당신은 전혀 추가 스레드가 없습니다. – Progman

+0

가끔은 실제로 프로그램이 실행되는 동안 Java VM 내부에서 도대체 무슨 일이 벌어지고 있는지 이해하지 못합니다. JRE는 여러 가지 최적화를 수행하며,이 경우 최종 스레드 '병합'연산을 사용하여 모든 스레드의 정수에 할당 된 값의 일종의 캐싱 (예 : 변수를 '여러 복사본으로 생성') 또는 지옥 ... 아마 스레드는 '기본'스레드가 아닙니다. 플랫폼에 맞는 JRE 코드를 살펴 봐야합니다 :) – gd1

+0

오, 이런 일반적인 시작은 혼란을 야기합니까? – gd1

답변

4

만 주어진 단일 스레드에서 실행 한 코드, 그래서 -2146200243을 준 테스트 실행에 내 상자에서

// Don't call run(), which is a synchronous call, which doesn't start any threads 
// Call start(), which starts a new thread and calls run() *in that thread*. 
add.start(); 
sub.start(); 

: 당신이 실제로 두 개의 스레드를 시작 경우 항상 0의 결과를 제공합니다 당신은 참으로 비 - 제로 결과를 얻을 수 있습니다.

+0

나 한테 이겼다 : \ 저주의 당신 존 스 켓! –

+0

@Jon Ug. 나는 시작 전화를 전적으로 의미. 정신 건강 검사 주셔서 감사합니다. – Dejas

0

프로그램의 문제점은 OS 스레드를 생성하지 않으므로 프로그램이 기본적으로 단일 스레드라는 것입니다. Java에서 Thread.run()이 아닌 새 OS 스레드를 작성하려면 Thread.start()을 호출해야합니다. 이것은 초기 Java API에서 유감스러운 실수를 저질렀습니다. 그 실수는 디자이너가 ThreadRunnable으로 구현 한 것입니다.

add.start(); 
sub.start(); 
add.join(); 
sub.join(); 
2

당신이 정말로 start하지 run을 의미 가정.

대부분의 공통 플랫폼에서 ++/--은 다중 코어의 경우 원자 연산이 아니기 때문에 0이 아닌 값을 생성 할 가능성이 큽니다. 단일 코어/단일 CPU에서 하나의 명령어 (add/inc)로 컴파일되는 경우 ++/--이 원자 일 때 0이 될 가능성이 높지만 그 부분은 JVM에 의존합니다. 여기

확인 결과 : http://ideone.com/IzTT2

관련 문제