?
Solved

Can't stop while loop calling unsychronized counter method.

Posted on 2000-05-18
3
Medium Priority
?
250 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 800 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

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Question has a verified solution.

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

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…
In this post we will learn different types of Android Layout and some basics of an Android App.
Viewers will learn about the different types of variables in Java and how to declare them. Decide the type of variable desired: Put the keyword corresponding to the type of variable in front of the variable name: Use the equal sign to assign a v…
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:
Suggested Courses
Course of the Month12 days, 15 hours left to enroll

578 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