2014-11-24 6 views
0

자바에서 스레드가 액세스 할 때 매개 변수의 값을 사용하여 새 객체를 만들고 해당 객체를 private 변수에 저장하면 나중에 반환 될 수 있습니다. 그런 다음 다른 스레드가 장벽을 호출하면이 다른 매개 변수로 이전 개체를 완료합니다. 첫 번째 쌍은 잘 진행되고 나머지는 첫 번째 쌍이 만든 동일한 개체를받습니다.자바 모니터가 개인 변수에서 잘못된 값을 반환합니다.

private Barrier aBarrier; 
private boolean first = true; 

public synchronized Barrier pairUp(int id){  
    try{ 
     if(first){ 
      first = false; 

      aBarrier = new Barrier(); aBarrier.setFirst(id); 

      wait(); 
     } 
     else{ 
      first = true; 
      aBarrier.setLast(id); 

      notify(); 
     } 

    } 
    catch(InterruptedException e){System.out.printf("ERROR");} 

    return aBarrier; 
} 

위의 방법을 호출하는 모든 프로세스는 다음과 같습니다.

private int id = ID OF THE PROCESS, 14 RUN CONCURRENTLY SO FROM 0 TO 13 (this is set in the constructor method); 
public void run() { 
    while(true){ 
     myBarrier = pairUp(id); 
     myBarrier.goThrough(); 
     //Do stuff that doesn't matter here 
     // .... 

    } 
} 

Barrier 개체에는 두 개의 정수와 나중에 더 많은 작업을 수행 할 수있는 메서드가 포함되어 있습니다. 호출 전이나 후에 private 변수 aBarrier를 null로 재설정하면 항상 null이 반환됩니다. 내가 바보 같은 것을 놓치고있는 것처럼 느껴진다.

프로세스가 첫 번째 쌍 다음에 pairUp() 메서드를 호출하면 첫 번째 쌍을 가져옵니다. 나는 pairUp 메소드에서 어떤 프로세스가 먼저 왔는지를 구분하기 위해 이것을 사용한다.

미리 감사드립니다.

+0

포스트 오류를 ​​재생 완전한 프로그램. 프로그램이 기대하는 바를 알려주십시오. –

+0

이 처음 휘발성입니까? –

+0

aBarrier와 first가 선언 된 곳이 어디에도 표시되지 않습니다. 나는 당신의 문제가 그 변수에 있다고 생각합니다. 우리는 모든 것을 볼 필요가 있습니다. – djna

답변

0

Barrier 개체는 두 개의 정수와 나중에 더 많은 작업을 수행하는 방법을 포함합니다. 호출 전이나 후에 private 변수 aBarrier를 null로 재설정하면 항상 null이 반환됩니다. 나는 어리석은 일을 여기에서 놓치고있는 것처럼 느낀다.

나는 문제가 당신이/통화를 통지 대기 후 aBarrier를 반환하는하지만 후속 스레드에 의해 변경되었을 수 있다고 생각합니다. 변경되지 않도록 로컬 변수에 저장하는 것이 중요합니다.

synchronized 문이 다른 개체에서 동기화되도록 여러 버전의 래핑 개체가있을 수도 있습니다.

몇 가지 아래의 코드에서주의해야 할 :

  • System.out.println(...) 동기화를 변경합니다. 여기 조심해야 해.
  • aBarrier이 null이거나 그렇지 않으면 first 부울을 대체했습니다.

코드 :

public class Foo implements Runnable { 

    private static int NUM_THREADS = 14; 
    private static final AtomicInteger idCounter = new AtomicInteger(); 
    private static final ExecutorService threadPool = Executors.newFixedThreadPool(NUM_THREADS); 
    private static Barrier aBarrier = null; 

    public static void main(String[] args) { 
     // only 1 Foo object 
     Foo foo = new Foo(); 
     for (int i = 0; i < NUM_THREADS; i++) { 
      threadPool.execute(foo); 
     } 
    } 

    public synchronized Barrier pairUp(int id) { 
     Barrier barrier = aBarrier; 
     try { 
      if (barrier == null) { 
       barrier = new Barrier(); 
       barrier.first = id; 
       aBarrier = barrier; 
       wait(); 
      } else { 
       barrier.last = id; 
       aBarrier = null; 
       notify(); 
      } 
     } catch (InterruptedException e) { 
      // always a good pattern 
      Thread.currentThread().interrupt(); 
      e.printStackTrace(); 
      barrier = null; 
     } 
     // return local barrier because aBarrier might have changed 
     return barrier; 
    } 

    @Override 
    public void run() { 
     int id = idCounter.incrementAndGet(); 
     while (true) { 
      Barrier myBarrier = pairUp(id); 
      // System.out.println is synchronized so it may move the bug 
      System.out.println(id + ": " + myBarrier.first + " and " + myBarrier.last); 
     } 
    } 

    private static class Barrier { 
     int first; 
     int last; 
    } 
}