Solved

Can't stop while loop calling unsychronized counter method.

Posted on 2000-05-18
3
239 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

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

For beginner Java programmers or at least those new to the Eclipse IDE, the following tutorial will show some (four) ways in which you can import your Java projects to your Eclipse workbench. Introduction While learning Java can be done with…
In this post we will learn how to connect and configure Android Device (Smartphone etc.) with Android Studio. After that we will run a simple Hello World Program.
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…
The viewer will learn how to implement Singleton Design Pattern in Java.

829 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