/* A simple demonstration of race conditions and how to use synchronized to avoid them */ public class MultiThreadedCounter implements Runnable { private int n; /* how many times to increment */ private boolean goSlow; /* whether to go fast or slow */ private int howSlow; /* how slow to go--bigger is slower */ private boolean useSynchronized; /* whether to use synchronized methods or not */ private int count = 0; /* we accumulate a count */ private double sum = 0.0; /* this is just a time waster--see incrSlow below. */ /** return the count @return count of how many times incr has been called (supposedly) */ public int getCount() { return count; } /** return the sum @return sum of all terms added to sum when "wasting time" */ public double getSum() { return sum; } public void reset() { count = 0; sum = 0.0; } /** Increment count as quickly as Java allows. */ public void incr() { count++; /* Equivalent to count = count + 1; */ } /** Increment count, but in between, accumulate terms from a sin function operating at 1 Hz, 44100 samples per second. This function should, over the long term, sum to approximately zero. This is really done just to "waste time" to make the window of vulnerability larger for race conditions of incrementing the count. @param terms number of terms to accumulate to waste time */ public void incrSlow(int terms) { int oldCount; // = count; for (int i=0; i<1000; i++) sum+=Math.sin(i * (2 * Math.PI / 44100.0)); count = oldCount + 1; } /** Increment count as quickly as Java allows. */ public synchronized void incrSync() { count++; /* Equivalent to count = count + 1; */ } /** Increment count, but in between, accumulate terms from a sin function operating at 1 Hz, 44100 samples per second. This function should, over the long term, sum to approximately zero. This is really done just to "waste time" to make the window of vulnerability larger. @param terms number of terms to accumulate to waste time */ public synchronized void incrSlowSync(int terms) { int oldCount = count; for (int i=0; i<1000; i++) sum+=Math.sin(i * (2 * Math.PI / 44100.0)); count = oldCount + 1; } /** Create a thread that will increment count n times. @param n How many times to increment @param goSlow Whether to use the slow version @param howSlow How many terms to accmulate @param useSynchronized Whether to use Synchronized methods */ public MultiThreadedCounter(int n, boolean goSlow, int howSlow, boolean useSyncrhonized) { this.n = n; this.goSlow = goSlow; this.howSlow = howSlow; this.useSynchronized = useSynchronized; } /* run the thread and do the work of incrementing n times */ public void run () { for (int i=0; i