import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
  * Encapsulates two threads sharing a sum variable to which both add
  * numbers repeatedly.  Lost updates, one kind of race condition, are
  * prevented with the use of a lock.
  *
  */
class IntensiveSumNoRClock implements Runnable {
   // The three fields below are shared by both threads since
   // there is only ONE object created from this class;
   // `volatile' is no longer needed in the sum variable declaration
   // due to its use inside a locked block.
   /**
	 * The number of times to call the summation function.
	 */
   private int N = 0;
   /**
	 * The variable to which the two threads add numbers repeatedly.
	 */
   private long sum = 0;
   /**
	 * The lock shared by the threads.
	 */
   private Lock mutex = new ReentrantLock();

   /**
	 * Constructor.
	 * @param M The number of times to call the summation function.
	 */
   public IntensiveSumNoRClock(int M) { this.N = M; }

   /**
	 * The summation function simulates a CPU-intensive addition operation.
	 * @param j The initial value.
	 * @param k The number of times to loop.
	 * @return The total
	 */
   private long fn(long j, int k) {
	  long total = j;
	  for (int i = 1;  i <= k; i++) total += i;
	  return total;
   }

   /**
	 * Code for threads inside this object to execute.
	 */
   public void run() {
	  for (int m = 1; m <= N; m++) {
		 mutex.lock();                  // entry protocol
		 try {
			sum = fn(sum, m);           // critical section
		 } finally { mutex.unlock(); }  // exit protocol
	  }                   // unlock whether or not exceptions thrown
	  System.out.println("sum = " + sum);
   }
}
