Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

View RSS Feed

Tjstretch

Thread Volatility

Rate this Entry
Summary
This is put at the top for those who don't want to read the entire thing.
  • Threads get more volatile as more are added, up to a point
  • Thread volatility jumps drammatically on my computer between 4 and 8 threads.
  • Calling non-volatile variables is very inaccurate


Overview
I recently posted a forum thread that more Java Threads will increase volatility. While I had seen the side-effect volatility and it seemed intuitive enough, I decided that n order not go give bad advice. I created a SSCEE of the situation that I was trying to express. The numbers that I crunched are in the comments of the program.

Program
import java.util.ArrayList;
/**
 * This SSCEE shows how volatile threads can get, especially without
 * synchronization calls.  On my computer, these are the estimated averages,
 * please note that these are very, very much estimated at a glance.
 * 
 * All numbers are in millions
 * 
 * Threads : Est. Average | range
 *    2    :      12      | 11 - 13
 *    4    :      83      | 74 - 91
 *    8    :     200?     | 106 - 950
 *    16   :     200?     | 101 - 957 Peak volatility
 *    32   :     225?     | 107 - 941
 * @author Timothy Moore
 */
public class ThreadVolatilityCheck extends Thread
{
  /**
   * This counter is called by many different threads.
   */
  private static int counter = 0;
  /**
   * The threads status
   */
  private volatile boolean running;
  /**
   * Prepares the thread to be started
   */
  public ThreadVolatilityCheck()
  {
    running = true;
  }
  /**
   * UI Thread runs here
   */
  public static void main(String[] args)
  {
    int numThreads = 1; //5 threads for first run
    ArrayList<ThreadVolatilityCheck> threads = new ArrayList<ThreadVolatilityCheck>();
    for(int i = 0; i < 5; i++) //Double the threads every loop
    {
      numThreads *= 2;
      runExample(numThreads, threads);
      //Delay a bit in hopes to reduce the lag, as well as run the GC
      clearThreads(threads);
      System.out.println("Done! Running GC and delaying to reduce lag.");
      System.gc();
      try
      {
        Thread.sleep(1000);
      }catch(InterruptedException exc)
      {
        exc.printStackTrace();
        return;
      }
    }
  }
  /**
   * Run an example, reusing the arraylist.  This runs for 
   * 15 seconds, displaying the counter every second
   * @param num the number of threads
   * @param thrdList the list of threads
   */
  public static void runExample(int num, ArrayList<ThreadVolatilityCheck> thrdList)
  {
    System.out.println("Running an example that has "+num+" threads!");
    for(int i = 0; i < num; i++)
    {
      thrdList.add(new ThreadVolatilityCheck());
      thrdList.get(i).start();
    }
    //Clear it several times to make sure
 
    for(int i = 0; i < 15; i++)
    {
      try
      {
        Thread.sleep(1000);
      }catch(InterruptedException exc)
      {
        exc.printStackTrace();
        return;
      }
      System.out.println("In loop "+(i+1)+", counter was incremented "+counter+" times.");
      for(int i2 = 0; i2 < 5; i2++) //Hard to clear with the threads going on so fast
      {
        counter = 0;
        try
        {
          Thread.sleep(10);
        }catch(InterruptedException exc)
        {
          exc.printStackTrace();
          return;
        }
      }
    }
  }
  /**
   * Stops each thread, and then clears the list.
   * 
   * @param thrdList the thread list
   */
  public static void clearThreads(ArrayList<ThreadVolatilityCheck> thrdList)
  {
    if(thrdList.size() > 0)
    {
      //Clear the list
      for(int i = 0; i < thrdList.size(); i++)
      {
        thrdList.get(i).running = false;
      }
      thrdList.clear();
    }
  }
  @Override
  public void run()
  {
    while(running)
    {
      counter++;
      /*try
      {
        Thread.sleep(5);  //Use this only if you have to.  This will make results much less clear, but
      }catch(InterruptedException exc) //will remove the lag your computer might get
      {
        exc.printStackTrace();
        return;
      }*/
    }
  }
}
Java web start:
Download
Example Console Log
Running an example that has 2 threads!
In loop 1, counter was incremented 118277530 times.
In loop 2, counter was incremented 240736625 times.
In loop 3, counter was incremented 120427092 times.
In loop 4, counter was incremented 240909394 times.
In loop 5, counter was incremented 119488030 times.
In loop 6, counter was incremented 121686245 times.
In loop 7, counter was incremented 248381632 times.
In loop 8, counter was incremented 116726346 times.
In loop 9, counter was incremented 120301259 times.
Running an example that has 2 threads!
In loop 1, counter was incremented 115030522 times.
In loop 2, counter was incremented 119786184 times.
In loop 3, counter was incremented 116040019 times.
In loop 4, counter was incremented 116059952 times.
In loop 5, counter was incremented 118205698 times.
In loop 6, counter was incremented 117622991 times.
In loop 7, counter was incremented 121463368 times.
In loop 8, counter was incremented 124049904 times.
In loop 9, counter was incremented 135277324 times.
In loop 10, counter was incremented 127150703 times.
In loop 11, counter was incremented 123867924 times.
In loop 12, counter was incremented 126675289 times.
In loop 13, counter was incremented 119651963 times.
In loop 14, counter was incremented 116634252 times.
In loop 15, counter was incremented 124676975 times.
Done! Running GC and delaying to reduce lag.
Running an example that has 4 threads!
In loop 1, counter was incremented 80441306 times.
In loop 2, counter was incremented 79333766 times.
In loop 3, counter was incremented 90902937 times.
In loop 4, counter was incremented 78883683 times.
In loop 5, counter was incremented 80974920 times.
In loop 6, counter was incremented 74613978 times.
In loop 7, counter was incremented 86349188 times.
In loop 8, counter was incremented 79928735 times.
In loop 9, counter was incremented 91211886 times.
In loop 10, counter was incremented 76407633 times.
In loop 11, counter was incremented 79752390 times.
In loop 12, counter was incremented 80749137 times.
In loop 13, counter was incremented 82692819 times.
In loop 14, counter was incremented 82302890 times.
In loop 15, counter was incremented 80635122 times.
Done! Running GC and delaying to reduce lag.
Running an example that has 8 threads!
In loop 1, counter was incremented 94999368 times.
In loop 2, counter was incremented 89438695 times.
In loop 3, counter was incremented 104784768 times.
In loop 4, counter was incremented 111052720 times.
In loop 5, counter was incremented 83219078 times.
In loop 6, counter was incremented 71943210 times.
In loop 7, counter was incremented 106010822 times.
In loop 8, counter was incremented 96757333 times.
In loop 9, counter was incremented 120123371 times.
In loop 10, counter was incremented 89143556 times.
In loop 11, counter was incremented 182450852 times.
In loop 12, counter was incremented 86592873 times.
In loop 13, counter was incremented 97944935 times.
In loop 14, counter was incremented 79801599 times.
In loop 15, counter was incremented 99167349 times.
Done! Running GC and delaying to reduce lag.
Running an example that has 16 threads!
In loop 1, counter was incremented 94321197 times.
In loop 2, counter was incremented 95704767 times.
In loop 3, counter was incremented 261301721 times.
In loop 4, counter was incremented 90415565 times.
In loop 5, counter was incremented 90370814 times.
In loop 6, counter was incremented 116607901 times.
In loop 7, counter was incremented 114454520 times.
In loop 8, counter was incremented 156387594 times.
In loop 9, counter was incremented 103858756 times.
In loop 10, counter was incremented 92475147 times.
In loop 11, counter was incremented 101842490 times.
In loop 12, counter was incremented 124823121 times.
In loop 13, counter was incremented 125901171 times.
In loop 14, counter was incremented 122276894 times.
In loop 15, counter was incremented 85608739 times.
Done! Running GC and delaying to reduce lag.
Running an example that has 32 threads!
In loop 1, counter was incremented 94154800 times.
In loop 2, counter was incremented 107724767 times.
In loop 3, counter was incremented 131514220 times.
In loop 4, counter was incremented 80345155 times.
In loop 5, counter was incremented 192092932 times.
In loop 6, counter was incremented 123248945 times.
In loop 7, counter was incremented 122500074 times.
In loop 8, counter was incremented 157550605 times.
In loop 9, counter was incremented 79583480 times.
In loop 10, counter was incremented 110221493 times.
In loop 11, counter was incremented 133837107 times.
In loop 12, counter was incremented 125375768 times.
In loop 13, counter was incremented 124613638 times.
In loop 14, counter was incremented 126575643 times.
In loop 15, counter was incremented 87293589 times.
Done! Running GC and delaying to reduce lag.

Warning
If you run the program, it will sky-rocket your CPU into oblivion

Updated March 13th, 2012 at 02:26 PM by Tjstretch

Categories
Uncategorized

Comments

  1. copeg's Avatar
    permalink
    I honestly don't really understand exactly what the SSCCE is attempting to demonstrate.