title: Java Threads reading and writing from a shared stack array
body: <p>The result of this program should be the same with 1 or 2 or 3 threads. However, the result with thread 1 is the real one. I think I am meshing up with shared and private variables, what am I doing wrong? Threads have to read from the stack an interval and then calculate the quadrature model.If the error is small enough (i.e. within the specified accuracy) then we have the solution. If the error is still too large, the interval is divided into two with half the required error given to each half of the interval. The quadrature is applied
  again and so on until the error is small enough.
  The main problem arises through premature termination of the
  threads. The stack may be empty, but another thread might be about to place new tasks on it. The solution to this is to keep a count of the "active" threads, that is, the ones which are currently processing an interval. Then the code should terminate only when the stack is empty and there are no active threads...</p>
  
  <p>Please, any help would be very appreciate it?</p>
  
  <p>Cheers</p>
  
  <pre><code> import java.lang.Integer;
  
  
  class quadtest  {
  
  /* Adaptive Quadrature Code. Finds the value of an integral of a 
     function on a closed interval to a specified accuracy.
  */
  
    public static void main (String args[]) {
  
      int nthreads = Integer.parseInt(args[0]);
  
      double left, right, eps;
      double start_time, time;
  
      Quad quad =null;
      //Counter counter = new Counter();
  
      left  = 0.0;
      right = 1.0;
      eps   = 1.0E-11;
  
      System.out.println("Adaptive Quadrature Program \n");
      System.out.println("eps="+eps+"    n=10000");
      start_time = System.currentTimeMillis();
  
      //Start threads
      Thread thread_object [] = new Thread[nthreads];
  
      for(int i=0;i&lt;nthreads;i++){    
          quad = new Quad(left,right,eps,i,nthreads);
          thread_object[i]=new Thread(quad);
      }
      for(int i=0;i&lt;nthreads;i++){    
          thread_object[i].start();
      }
      //Join the threads
      for(int i=0;i&lt;nthreads;i++){
          try{
          thread_object[i].join();
          }catch(InterruptedException x){}
      }
  
      time = (double) (System.currentTimeMillis()-start_time) / 1000.;
      System.out.println("Result  = "  + quad.getResult() );
      System.out.println("Execution time = "  + time + " seconds ");
  
  
      }
  }
  
      import java.lang.Runnable;
  import java.util.concurrent.atomic.AtomicInteger;
  
  class Quad implements Runnable{
      //Shared Variables 
      static volatile double [][] stack;
      static volatile boolean first=false;
      static volatile double FinalResult;
      static AtomicInteger threadCounter;
      static AtomicInteger writing;
      static AtomicInteger stackpointer;
      static int nthreads;
      //Constants
      static final int stacksize = 1000;
      static final int il = 0;
      static final int ir = 1;
      static final int ie = 2;
      static final int dims = 3;
      //Private Variables
      private  int tid;
      double left,right,eps;
      private double result;
      private double l,r,ep;
  
  
      public Quad(double left, double right, double eps,int tid,int nthreads) {
  
          this.left = left;
          this.right = right;
          this.eps = eps; 
          this.tid=tid;
          Quad.nthreads = nthreads;
          result = 0.0;
          //Only one thread will do it
          if(first==false){
              first=true;
              stack        =  new double [dims][stacksize];
              threadCounter=  new AtomicInteger(0);
              writing      =  new AtomicInteger(0);
              stackpointer =  new AtomicInteger(1);
  
              stack[il][stackpointer.get()] = left;
              stack[ir][stackpointer.get()] = right;
              stack[ie][stackpointer.get()] = eps;
              FinalResult=0.0;
           }
      }
      public void run(){
          stackops();
          add();
      }
  
     public void stackops() {
  
         double abserror,m, est1, est2;
  
         while ((stackpointer.get() &gt;= 1)|| threadCounter.get()&gt;0) {
  
  
             // Pop next interval off stack.
             synchronized (this){
                 threadCounter.incrementAndGet();
                 while (writing.get()==1){}
                 pop();
             }
             // Compute estimates.
             m    = 0.5 * (l + r);
             est1 = 0.5 * (r - l) * (func(l) + func(r)) ;
             est2 = 0.5 * ((m - l) * (func(l) + func(m)) + (r - m) * 
                   (func(m) + func(r)));
             abserror = Math.abs(est2-est1) / 3.0;
  
  
             // Check for desired accuracy: push both halves onto the
             // stack if not accurate enough.        
             if (abserror &lt;= ep) {
                 result += est2;
                  //System.out.println("ERROR-&gt;ID "+tid+"-abserror="+abserror+"-ep="+ep );
                  //System.out.flush();
             } else {        
                 if (stackpointer.get()+ 2 &gt; stacksize) {
                 System.out.println("Stack too small, try stacksize = " 
                            + 2*stacksize);
                 }
                 //Push into the stack
                 synchronized (this){
                      push(m);
                  }
               }//end else
               threadCounter.decrementAndGet();
             }//end while
     }//end method
  
      private synchronized void add(){
          FinalResult +=result;
      }
  
      private void pop(){
          if(stackpointer.get()&gt;0){
              l   = stack[il][stackpointer.get()];
              r   = stack[ir][stackpointer.get()];
              ep  = stack[ie][stackpointer.get()];
              stackpointer.decrementAndGet();
          }
      }
      private void push (double m){
          writing.set(1);
              if(stackpointer.get()&gt;=-1){
                  stackpointer.incrementAndGet();
                  stack[il][stackpointer.get()] = l;
                  stack[ir][stackpointer.get()] = m;
                  stack[ie][stackpointer.get()] = ep * 0.5;
  
                  stackpointer.incrementAndGet();
                  stack[il][stackpointer.get()] = m;
                  stack[ir][stackpointer.get()] = r;
                  stack[ie][stackpointer.get()] = ep * 0.5;
              }
         writing.set(0);
      } 
  
      public  double getResult(){
          return FinalResult;
      }
  
      private double func(double x) {
  
      double q;
      int n;
  
      n = 10000;
      q = 1000.0;
  
      for(int i=0;i&lt;n;i++) {
          q -= x;
      }
      if (q == 1.0e10) System.out.println("q = " + q);
  
      return x * x;
  
      }
  }
  </code></pre>