title: Why do these threads return an incorrect calculation?
body: <p>I am quite new to concurrent programming and I am enjoying it so far :)! However I just realized how tricky concurrent programming.</p>
  
  <p>I have multiple threads which perform their own computations. Each thread operates on a certain variable and returns a result, however the result returned is incorrect. </p>
  
  <p>This class performs the thread calculations:</p>
  
  <pre><code>public class SharedDataThread extends Thread {
  
  private SharedData mySharedData;
  private String myThreadName;
  private static long testVariable = 0;
  
  // Setup the thread
  
  SharedDataThread(String name, SharedData sharedstuff) {
      super(name);
      mySharedData = sharedstuff;
      myThreadName = name;
  }
  
  
  public void run() {
  
      System.out.println(myThreadName + " is running");
      Thread me = Thread.currentThread(); // get a ref to the current thread
  
      if (me.getName() == "myThread1") {
          try {
              sleep(2000);
  
              mySharedData.acquireLock();
              System.out.println(me.getName()
                      + " is performing computations!");
  
              testVariable = testVariable + 20;
              testVariable = testVariable * 5;
              testVariable = testVariable / 3;
  
              System.out.println(me.getName() + " modified the value to : "
                      + testVariable + "\n");
  
              sleep(2000);
              mySharedData.releaseLock();
          } catch (InterruptedException e) {
              System.err.println("Failed to get lock when reading:" + e);
          }
      } else if (me.getName() == "myThread2") {
          try {
              sleep(2000);
  
              mySharedData.acquireLock();
              System.out.println(myThreadName
                      + " is performing computations!");
  
              testVariable = testVariable - 5;
              testVariable = testVariable * 10;
              testVariable = (long) (testVariable / 2.5);
  
              System.out.println(me.getName() + " modified the value to : "
                      + testVariable + "\n");
  
              sleep(2000);
              mySharedData.releaseLock();
          } catch (InterruptedException e) {
              System.err.println("Failed to get lock when reading:" + e);
          }
      } else if (me.getName() == "myThread3") {
          try {
              sleep(2000);
  
              mySharedData.acquireLock();
  
              System.out.println(me.getName()
                      + " is performing computations!");
  
              testVariable = testVariable - 50;
              testVariable = testVariable / 2;
              testVariable = testVariable * 33;
  
              System.out.println(me.getName() + " modified the value to : "
                      + testVariable + "\n");
  
              sleep(2000);
              mySharedData.releaseLock();
          } catch (InterruptedException e) {
              System.err.println("Failed to get lock when reading:" + e);
          }
      } else {
          try {
              sleep(2000);
  
              mySharedData.acquireLock();
              System.out.println(me.getName()
                      + " is performing computations!");
  
              testVariable = testVariable * 20;
              testVariable = testVariable / 10;
              testVariable = testVariable - 1;
  
              System.out.println(me.getName() + " modified the value to : "
                      + testVariable + "\n");
  
              sleep(2000);
  
              mySharedData.releaseLock();
          } catch (InterruptedException e) {
              System.err.println("Failed to get lock when reading:" + e);
          }
      }
      System.out.println("The final result of the variable is "
              + testVariable);
  }
  </code></pre>
  
  <p>}</p>
  
  <p>The threads are executed in another class with its own main thread of execution:</p>
  
  <pre><code>public class SharingExample {
  </code></pre>
  
  <p>public static void main(String[] args) {</p>
  
  <pre><code>SharedData mySharedData = new SharedData();
  
  
  SharedDataThread myThread1 = new SharedDataThread("myThread1", mySharedData);
  SharedDataThread myThread2 = new SharedDataThread("myThread2", mySharedData);
  SharedDataThread myThread3 = new SharedDataThread("myThread3", mySharedData);
  SharedDataThread myThread4 = new SharedDataThread("myThread4", mySharedData);
  
  
  // Now start the threads executing
  
  myThread1.start();
  myThread2.start();
  myThread3.start();
  myThread4.start();
  </code></pre>
  
  <p>}
  }</p>
  
  <p>the SharedData class is just a class for implementing locks and such.</p>
  
  <pre><code>public class SharedData {
  
    private boolean accessing=false; // true a thread has a lock, false otherwise
    private int threadsWaiting=0; // number of waiting writers
  
    // attempt to acquire a lock
    public synchronized void acquireLock() throws InterruptedException{
    Thread me = Thread.currentThread(); // get a ref to the current thread
    System.out.println(me.getName()+" is attempting to acquire a lock!");
  
    ++threadsWaiting;
      while (accessing) {  // while someone else is accessing or threadsWaiting &gt; 0
        System.out.println(me.getName()+" waiting to get a lock as someone else is accessing...");
        //wait for the lock to be released - see releaseLock() below
       wait();
      }
      // nobody has got a lock so get one
      --threadsWaiting;
      accessing = true;
      System.out.println(me.getName()+" got a lock!"); 
    }
  
    // Releases a lock to when a thread is finished
  
    public synchronized void releaseLock() {
        //release the lock and tell everyone
        accessing = false;
        notifyAll();
        Thread me = Thread.currentThread(); // get a ref to the current thread
        System.out.println(me.getName()+" released a lock!");
    }
  
  }
  </code></pre>
  
  <p>Where is the problem here?</p>