Solved

Can't stop while loop calling unsychronized counter method.

Posted on 2000-05-18
3
238 Views
Last Modified: 2013-11-23

D:\course\threading>java Strange1
unsynchronized Start
synchronized Start
281382614 unsynchronized iterations.
7041533 synchronized iterations.
synchronized Stop
849434797 unsynchronized iterations.
7041533 synchronized iterations.

This behavior was discovered while experimenting with Synchronization and and the impact on Real Time.

Two threads are started running a counter.  One counts with an unsynchronized method.  The other counts with a synchronized method.  

After 10 seconds, a static variable is updated to stop the while loops that are doing the counting.  Note that the unsynchronized counter did not stop.

The two counts are output and, sure enough, the unsynchronized counter had many more cycles than the synchronized counter.

After waiting another 10 seconds, the counters are output again.  The synchronized count is still the same, confirming that it really did stop.  The unsynchronized count, is greatly increased, confirming that it really did not stop.  

I tried using an instance variable to stop the loop with the same results.  Why does the loop around the unsynchronized method call not notice that the static variable is now failing the while condition?

So I added some more code to the unsynchronized method and it behaved properly.

D:\course\Exercises>java Strange
unsynchronized Start
synchronized Start
527394 unsynchronized iterations.
5791502 synchronized iterations.
unsynchronized Stop
synchronized Stop
527395 unsynchronized iterations.
5791503 synchronized iterations.

Why the difference in behavior?

Thank you,
Harold Meder.
                                                         
--------------------------------------
import java.io.*;
public class Strange1 implements Runnable
{
   
   private int count = 0;
   private boolean sync = false;
   private static boolean cont = true;
   
   public Strange1()
   {
   }
   
   public Strange1(boolean _sync)
   {sync = _sync;
   }
   
   public void run() {
      count = 0;
      if(sync == true){
          System.out.println("synchronized Start");
          while (cont == true) {scount();}
          System.out.println("synchronized Stop");
      }
      else {
          System.out.println("unsynchronized Start");
          while (cont == true) {count();}
          System.out.println("unsynchronized Stop");
      }

   }

   private void count()
   {count++;
   }
   
   private synchronized void scount()
   {count++;
   }
   
   public static void main(String[] args) throws InterruptedException
   {
     Strange1 sync = new Strange1();
     Strange1 ssync = new Strange1(true);

    {
      Thread thread = new Thread(sync);
        thread.setPriority(Thread.MIN_PRIORITY);
      Thread sthread = new Thread(ssync);
        sthread.setPriority(Thread.MIN_PRIORITY);
      thread.start();
      sthread.start();
    }
      Thread.sleep(10000);
      cont = false;
    System.out.println(sync.count + " unsynchronized iterations.");
    System.out.println(ssync.count + " synchronized iterations.");
      Thread.sleep(10000);
    System.out.println(sync.count + " unsynchronized iterations.");
    System.out.println(ssync.count + " synchronized iterations.");
   }
}
----------------------------------------
import java.io.*;
public class Strange implements Runnable
{
   
   private int count = 0;
   private boolean sync = false;
   private static boolean cont = true;
   
   public Strange()
   {
   }
   
   public Strange(boolean _sync)
   {sync = _sync;
   }
   
   public void run() {
      String temp;
      count = 0;
      if(sync == true){
          System.out.println("synchronized Start");
          while (cont == true) {scount();}
          System.out.println("synchronized Stop");
      }
      else {
          System.out.println("unsynchronized Start");
          while (cont == true) {temp = " " + cont;count();}
          System.out.println("unsynchronized Stop");
      }

   }

   private void count()
   {count++;
   }
   
   private synchronized void scount()
   {count++;
   }
   
   public static void main(String[] args) throws InterruptedException
   {
     Strange sync = new Strange();
     Strange ssync = new Strange(true);

    {
      Thread thread = new Thread(sync);
        thread.setPriority(Thread.MIN_PRIORITY);
      Thread sthread = new Thread(ssync);
        sthread.setPriority(Thread.MIN_PRIORITY);
      thread.start();
      sthread.start();
    }
      Thread.sleep(10000);
      cont = false;
    System.out.println(sync.count + " unsynchronized iterations.");
    System.out.println(ssync.count + " synchronized iterations.");
      Thread.sleep(10000);
    System.out.println(sync.count + " unsynchronized iterations.");
    System.out.println(ssync.count + " synchronized iterations.");
   }
}

                                                                               

0
Comment
Question by:hwmeder
  • 2
3 Comments
 
LVL 19

Accepted Solution

by:
Jim Cakalic earned 200 total points
ID: 2821216
Well, I'm not entirely sure why -- I'm still trying to wade through the heavily formal language of the JVM spec -- but I am pleased to tell you two things about your problem.

First, it appears to be fixed in jdk1.3. Both versions of your class execute as expected.

Second, I was able to duplicate the problem on jdk1.2 and was able to correct it by the 'volatile' modifier to the cont boolean. My guess at this point is that the 1.2 JVM tries to optimize access to the variable by loading the value once on loop entry and using the loaded value for the duration of the loop. Strange1's additional code would not allow the JVM to perform this optimization because it accessed the value of cont within the loop thereby forcing a load operation. Notice that it isn't just _any_ additional code that will cause this. The cont variable must be accessed to induce this behavior.

In any event, try adding volatile to the declaration of cont. This should correct the problem without requiring you to upgrade to the latest jdk.

BTW, I compiled the class files using jikes -- not the javac compiler. And I tested the same class files on the JVMs from jdk1.2 and jdk1.3. I think this eliminates the javac compiler as the culprit.

Best regards,
Jim Cakalic
0
 

Author Comment

by:hwmeder
ID: 2822275
Adding the volatile modifier to the cont boolean resolved the problem for me.  I am using javac and jvm from jdk 1.2.2 in a DOS environment on Windows 95.

I guess this suggests that there is a defect in the JVM.

   Thank you,
      Harold Meder.
0
 
LVL 19

Expert Comment

by:Jim Cakalic
ID: 2824362
Sacrilege!! Who woulda thunk it possible?
;-)
0

Featured Post

Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

By the end of 1980s, object oriented programming using languages like C++, Simula69 and ObjectPascal gained momentum. It looked like programmers finally found the perfect language. C++ successfully combined the object oriented principles of Simula w…
Are you developing a Java application and want to create Excel Spreadsheets? You have come to the right place, this article will describe how you can create Excel Spreadsheets from a Java Application. For the purposes of this article, I will be u…
Viewers learn about the scanner class in this video and are introduced to receiving user input for their programs. Additionally, objects, conditional statements, and loops are used to help reinforce the concepts. Introduce Scanner class: Importing…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.

832 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question