The Artima Developer Community
Sponsored Link

Weblogs Forum
Are your loops volatile controlled?

5 replies on 1 page. Most recent reply: Jan 7, 2006 7:02 PM by Keith Ray

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 5 replies on 1 page
Gregg Wonderly

Posts: 317
Nickname: greggwon
Registered: Apr, 2003

Are your loops volatile controlled? (View in Weblogs)
Posted: Jan 3, 2006 12:28 PM
Reply to this message Reply
Summary
I recently noticed in JRE1.5 that HotSpot is yanking loop controls as invariant when not marked as volatile. Have you encountered this?
Advertisement
The Java Memory Model was formally updated in JSE1.5 to include a strict definition and implementation of the volatile keyword. In JSE1.4, Sun had already started working on making their VM compatible with the better specification of synchronized and volatile that would be implemented in JSE1.5. Recently, I started using a P4 based laptop with Hyper-Threading, that now makes my software run in a multi-processor environment. This changes everything...

After starting to use the new machine, I noticed that I started getting bit by an optization where loop control, boolean value tests are being yanked out of the loop.

The basic structure of the problematic software is as follows.


class MyClass ... implements Runnable {
    private boolean stopping;
    public void stop() {
        stopping = true;
        // maybe close a socket etc.
    }

    public void run() {
        while( !stopping ) {
            try {
                ... do some work ...
            } catch( Exception ex ) {
                ... process exception ...
            }
        }
    }
}

What I am seeing is that HotSpot is apparently (this I have gleened from conversations on Doug Lea's Concurrency-Interest list) yanking the while( !stopping) { } block out and replacing it with an if( !stopping ) { } block surrounding a while(true) { } block!


class MyClass ... implements Runnable {
    private boolean stopping;
    public void stop() {
        stopping = true;
        // maybe close a socket etc.
    }

    public void run() {
        if( !stopping ) {
            while(true) {
                try {
                    ... do some work ...
                } catch( Exception ex ) {
                    ... process exception ...
                }
            }
        }
    }
}

The end result, of course, is that a call to stop(); will never be able to stop the looping thread executing in run(){ }.

What I've found, of course, is that if I go ahead and declare stopping as volatile that suddenly the code works as expected!

I ran this code for a long time on a single processor laptop on JSE1.5 even, and don't recall that I saw this happening. I wonder if this optimization only happens on MP machines.

So, beware... If you have been using loop controls like this and have neither made the references happen inside synchronized code, or made the variables volatile, you may be getting bit by this "optimization!"


James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Are your loops volatile controlled? Posted: Jan 3, 2006 12:36 PM
Reply to this message Reply
I am assuming that stop() and stopping are not referred to by the run method or any of it's method calls. If that is the case, I would hope adding such a reference would defeat this optimization. I can test it later but if you have a minute can you give it a try.

The only way I can think that this optimization is being done is through some sort of escape analysis. I thought the escape analysis features that allow this kind of optimization and stack-based allocation were not going to be introduced until 1.6.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Are your loops volatile controlled? Posted: Jan 3, 2006 12:44 PM
Reply to this message Reply
> So, beware... If you have been using loop controls like
> this and have neither made the references happen inside
> synchronized code, or made the variables volatile, you may
> be getting bit by this "optimization!"

I agree this can be a serious concern. On the other hand, this kind of code has been known to be unsafe for years. That it ever worked is only because of JVM lenience. For a while now (if not always) it's been the case that threads can cache this kind of value and that there is no requirement to flush, ever. Only by using synchronization marking the field volatile was a flush required. My understand was that there was some issue with volatile not being an absolute guarantee as it should have been.

Is it possible that you are seeing a cache issue and there is no optimization? In other words, how did you determine this is what is happening?

Gregg Wonderly

Posts: 317
Nickname: greggwon
Registered: Apr, 2003

Re: Are your loops volatile controlled? Posted: Jan 3, 2006 3:18 PM
Reply to this message Reply
> > So, beware... If you have been using loop controls
> like
> > this and have neither made the references happen inside
> > synchronized code, or made the variables volatile, you
> may
> > be getting bit by this "optimization!"
>
> I agree this can be a serious concern. On the other hand,
> this kind of code has been known to be unsafe for years.
> That it ever worked is only because of JVM lenience. For
> a while now (if not always) it's been the case that
> threads can cache this kind of value and that there is no
> requirement to flush, ever. Only by using synchronization
> marking the field volatile was a flush required. My
> understand was that there was some issue with volatile not
> being an absolute guarantee as it should have been.

The places where I am find this is in old client code that would disconnect socket listening threads or shutdown other similar activity in other threads. It always seemed to work fine until I got the P4 w/HT laptop.

> Is it possible that you are seeing a cache issue and there
> is no optimization? In other words, how did you determine
> this is what is happening?

Given that it started being very noticable in the P4 w/HT laptop, it might be that it is actually a caching issue more than an optimization. Since it's happening in HotSpot, I am not sure how to tell exactly what the true flow of execution is.

I am guessing that this is the loop invariant optimization occuring based on past coversations on the concurrency-interests list. But, it is more of a guess what the cause is. The change to using volatile, or putting synchronized around the references and writes solves the problem, for either potential source.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Are your loops volatile controlled? Posted: Jan 4, 2006 6:49 AM
Reply to this message Reply
> > Is it possible that you are seeing a cache issue and
> there
> > is no optimization? In other words, how did you
> determine
> > this is what is happening?
>
> Given that it started being very noticable in the P4 w/HT
> laptop, it might be that it is actually a caching issue
> more than an optimization. Since it's happening in
> HotSpot, I am not sure how to tell exactly what the true
> flow of execution is.
>
> I am guessing that this is the loop invariant optimization
> occuring based on past coversations on the
> concurrency-interests list. But, it is more of a guess
> what the cause is. The change to using volatile, or
> putting synchronized around the references and writes
> solves the problem, for either potential source.

It's also possible that HotSpot is caching more aggresively in 1.5, possibly because of the improved memory model.

Keith Ray

Posts: 658
Nickname: keithray
Registered: May, 2003

Re: Are your loops volatile controlled? Posted: Jan 7, 2006 7:02 PM
Reply to this message Reply
Regardless of implementation peculiarities, if you EVER have two threads accessing the same variable, you need to declare that variable volatile (or use other synchronization features). Loop optimizations do not really enter into it.

Volatile tells the compiler/vm to make sure that the variable doesn't get cached. For example... cached in the per-cpu cache on a multiple-cpu machine.

Forgetting to declare a variable volatile in a single-cpu machine, you won't see a problem, but a multiple-cpu machine, you may or may not see a problem. Just do what the language-spec tells you to do and declare it volatile.

Flat View: This topic has 5 replies on 1 page
Topic: Java API Design Guidelines Previous Topic   Next Topic Topic: How is Moore's Law really changing computing?

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use