2014-11-14 3 views
1

내 코드를 컴파일 할 때 교착 상태에있는 것처럼 보입니다. 어떻게 해결할 수 있는지 모르겠습니다. 각 스레드가 파이프 라인에서 선행 노드를 읽고 결과적으로 다음 스레드에 쓸 수있는 버퍼로 함께 연결된 스레드 시퀀스로 파이프 라인을 작성하려고합니다. 전반적인 목표는 무작위로 생성 된 데이터의 arraylist를 10 개의 스레드 이상으로 쏟아서 정렬하는 것입니다.내 코드가 교착 상태에 있습니까?

class Buffer{ 
    // x is the current node 
    private int x; 
    private boolean item; 
    private Lock lock = new ReentrantLock(); 
    private Condition full = lock.newCondition(); 
    private Condition empty = lock.newCondition(); 

    public Buffer(){item = false;} 

    public int read(){ 
     lock.lock(); 
     try{ 
      while(!item) 
      try{full.await();} 
      catch(InterruptedException e){} 
      item = false; 
      empty.signal(); 
      return x; 
    }finally{lock.unlock();} 
    } 

    public void write(int k){ 
     lock.lock(); 
     try{ 
     while(item) 
      try{empty.await();} 
      catch(InterruptedException e){} 
     x = k; item = true; 
     full.signal(); 
     }finally{lock.unlock();} 

    } 
} 

class Pipeline extends Thread { 

    private Buffer b; 
    //private Sorted s; 
    private ArrayList<Integer> pipe; // array pipeline 
    private int ub; // upper bounds 
    private int lb; // lower bounds 

    public Pipeline(Buffer bf, ArrayList<Integer> p, int u, int l) { 
     pipe = p;ub = u;lb = l;b = bf;//s = ss; 
    } 

    public void run() { 
     while(lb < ub) { 
      if(b.read() > pipe.get(lb+1)) { 
       b.write(pipe.get(lb+1)); 
      } 

      lb++; 
     } 

     if(lb == ub) { 
      // store sorted array segment 
      Collections.sort(pipe); 
      new Sorted(pipe, this.lb, this.ub); 
     } 
    } 

} 

class Sorted { 

    private volatile ArrayList<Integer> shared; 
    private int ub; 
    private int lb; 

    public Sorted(ArrayList<Integer> s, int u, int l) { 
     ub = u;lb = l;shared = s; 
     // merge data to array from given bounds 
    } 
} 

class Test1 { 
    public static void main(String[] args) { 


     int N = 1000000; 
     ArrayList<Integer> list = new ArrayList<Integer>(); 

     for(int i=0;i<N;i++) { 
      int k = (int)(Math.random()*N); 
      list.add(k); 
     } 

     // write to buffer 
     Buffer b = new Buffer(); 
     b.write(list.get(0)); 

     //Sorted s = new Sorted(); 

     int maxBuffer = 10; 
     int index[] = new int[maxBuffer+1]; 
     Thread workers[] = new Pipeline[maxBuffer]; 

     // Distribute data evenly over threads 
     for(int i=0;i<maxBuffer;i++) 
      index[i] = (i*N)/maxBuffer; 

     for(int i=0;i<maxBuffer;i++) { 
      // create instacen of pipeline 
      workers[i] = new Pipeline(b,list,index[i],index[i+1]); 
      workers[i].start(); 
     } 

     // join threads 
     try { 
      for(int i=0;i<maxBuffer;i++) { 
       workers[i].join(); 
      } 
     } catch(InterruptedException e) {} 

     boolean sorted = true; 

     System.out.println(); 
     for(int i=0;i<list.size()-1;i++) { 
      if(list.get(i) > list.get(i+1)) { 
       sorted = false; 
      } 
     } 

     System.out.println(sorted); 
    } 
} 

답변

0

실행 방법을 시작하면 첫 번째 스레드가 full.await()에 도달 할 때까지 모든 스레드가 차단됩니다. 그리고 나서 하나씩, 모든 스레드는 full.await()를 치게 될 것입니다. 그들은이 신호를 기다릴 것입니다.

그러나 full.signal이 발생하는 유일한 장소는 read 메소드 중 하나가 완료된 후입니다. 이 코드는 절대로 도달하지 않으므로 (신호가 발사되지 않기 때문에) 결국 모든 스레드가 대기하게됩니다.

간단히 말해서, 읽기가 끝난 후에 만 ​​쓰기 트리거가 발생합니다. 논리를 뒤집어서 비어있는 상태로 시작하고 버퍼 (신호 등 등)에 쓰고 스레드가 읽으려고하면 제대로 작동 할 것으로 기대합니다.

일반적으로 파이프 라인에 쓰기를 원한다면 읽고 쓰기를 원한다. (또는 읽을 것이 없습니다).

내가 코드를 잘못 읽지 않았 으면 좋겠지 만 처음 스캔 할 때 보았습니다.

0

Buffer 읽기 모드와 쓰기 모드 사이를 전환합니다. 각각의 읽기에는 쓰기, 읽기 등의 읽기가 이어져야합니다.

버퍼는 처음에 main 방법으로 작성합니다.

이제 스레드 중 하나가 if(b.read() > pipe.get(lb+1)) { (Pipeline#run)에 도달했습니다. 조건이 false로 평가되면 아무것도 쓰이지 않습니다. 그리고 다른 모든 스레드는 여전히 동일한 if(b.read()이어야하므로 진행할 수없는 모든 읽기 스레드로 끝납니다. else 지점에 글을 써야하거나 여러 번 읽을 수 있어야합니다.

관련 문제