wood burning stoves 2.0*
The moose likes Beginning Java and the fly likes Use of Class Variables Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "Use of Class Variables" Watch "Use of Class Variables" New topic
Author

Use of Class Variables

Terry Tucker
Greenhorn

Joined: Jan 21, 2013
Posts: 22

Greetings:

I am revamping an older report at work that used several different hashes and several different methods for accumulating the data based on the report options. A new requirement for the report demanded a different approach to how the query data was processed. In order to handle this, I wrote a new class which gathers the data by maintaining a couple of statically defined hashes within the new class where the key is a unique String value and the value is a class reference to an instance of the new class that contains all the report data for a given customer. In other words, the class maintains itself providing access to the data as in CollectionData.getCustHash().

I received an email from another developer last evening that says:
"Hey, I think it would be a good idea to change the ReportAgeAR and CollectionData to not use static variables. As is, if two users ran the report at approximately the same time, the data could get corrupted. Agent Access and the smartphone web service both call that report and support many users in the same JVM."

Am I to understand that class variables can be trampled on by another user running the same report? The bulk of my experience is in C where every user had his own namespace. I did some Googling on this subject and some say static variables very bad but I didn't find any that said what was quoted above. Others say say the exact opposite.

What saith ye?

Thanks...
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4442
    
    5

Your colleague is right. Class variables are shared by all instances of a class. The only thread-safe use of these would be if they were marked as final and initialized immediately after the class is loaded and before any objects of that class are instantiated. In addition, there should be no way to change these variables at any time after they are initialized. If each object of this class requires its own values for these variables, then you should make them non-static members. Depending on how you instantiate and use the objects, this may be sufficient or you may still need to synchronize access to the variables.


Junilu - [How to Ask Questions] [How to Answer Questions]
Stevens Miller
Ranch Hand

Joined: Jul 26, 2012
Posts: 523
    
    3

Junilu Lacar wrote:Your colleague is right. Class variables are shared by all instances of a class. The only thread-safe use of these would be if they were marked as final and initialized immediately after the class is loaded and before any objects of that class are instantiated. In addition, there should be no way to change these variables at any time after they are initialized. If each object of this class requires its own values for these variables, then you should make them non-static members. Depending on how you instantiate and use the objects, this may be sufficient or you may still need to synchronize access to the variables.


Couple of questions on that, Junilu:

1. When you said "Class variables," did you mean "Static variables"?

2. If all instances of a class were running in their own thread, and were to be stopped without having to keep a reference to each instance elsewhere, mightn't it be a viable way to stop them to set a static flag they all shared?
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Stevens Miller wrote:
1. When you said "Class variables," did you mean "Static variables"?


"Class variable" is what the JLS calls a static member variable, and "instance variable" is what it calls a non-static member variable.

2. If all instances of a class were running in their own thread, and were to be stopped without having to keep a reference to each instance elsewhere, mightn't it be a viable way to stop them to set a static flag they all shared?


Instances don't run, but yes, a class variable as a flag is one valid approach.
Junilu Lacar
Bartender

Joined: Feb 26, 2001
Posts: 4442
    
    5

Jeff Verdegan wrote: a class variable as a flag is one valid approach.
Although you have to be careful to synchronize access to it.
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Junilu Lacar wrote:
Jeff Verdegan wrote: a class variable as a flag is one valid approach.
Although you have to be careful to synchronize access to it.


Or make it volatile. But of course this applies to any shared variable.
Stevens Miller
Ranch Hand

Joined: Jul 26, 2012
Posts: 523
    
    3

Jeff Verdegan wrote:
Junilu Lacar wrote:
Jeff Verdegan wrote: a class variable as a flag is one valid approach.
Although you have to be careful to synchronize access to it.


Or make it volatile. But of course this applies to any shared variable.

And it's not the same thing (that is, volatile != synchronized). Using it as a "stop" flag doesn't inherently require any synchronization.
Stevens Miller
Ranch Hand

Joined: Jul 26, 2012
Posts: 523
    
    3

Jeff Verdegan wrote:
Stevens Miller wrote:
1. When you said "Class variables," did you mean "Static variables"?


"Class variable" is what the JLS calls a static member variable, and "instance variable" is what it calls a non-static member variable.

Same thing, then?

2. If all instances of a class were running in their own thread, and were to be stopped without having to keep a reference to each instance elsewhere, mightn't it be a viable way to stop them to set a static flag they all shared?


Instances don't run, but yes, a class variable as a flag is one valid approach.

Ah, quite right: instances don't run; methods do. And the number of threads started by one method could be unlimited. My point remains that a shared flag could be consulted to stop them all, and that flag might be a static/class variable.
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Stevens Miller wrote:
Jeff Verdegan wrote:
Junilu Lacar wrote:
Jeff Verdegan wrote: a class variable as a flag is one valid approach.
Although you have to be careful to synchronize access to it.


Or make it volatile. But of course this applies to any shared variable.

And it's not the same thing (that is, volatile != synchronized). Using it as a "stop" flag doesn't inherently require any synchronization.


It's true that volatile != synchronized, but anything that's done with volatile can also be done with synchronization. (The converse isn't true, however.)

If we're going to use it as a stop flag, then we have to do one of the following, to ensure that all threads see our write:

  • Make it volatile.
  • Synchronize all access to it.
  • Use an AtomicXxx or a CountdownLatch or other suitable approach from java.util.concurrent.
  • Terry Tucker
    Greenhorn

    Joined: Jan 21, 2013
    Posts: 22



    The simple program above increments a class variable (static variable) 10 million times. I have a shell script that runs this program in the background twice. They should be stomping on one another in this scenario if what I have been told regarding static variables is correct. I am simply trying to demonstrate the problem and am unable to do so. Is my test invalid?

    Thanks...
    Stevens Miller
    Ranch Hand

    Joined: Jul 26, 2012
    Posts: 523
        
        3

    Jeff Verdegan wrote:
    It's true that volatile != synchronized, but anything that's done with volatile can also be done with synchronization. (The converse isn't true, however.)

    Well, not without engaging in a tedious exercise in computer science that would serve no useful purpose, anyway.

    If we're going to use it as a stop flag, then we have to do one of the following, to ensure that all threads see our write:

  • Make it volatile.
  • Synchronize all access to it.
  • Use an AtomicXxx or a CountdownLatch or other suitable approach from java.util.concurrent.


  • Agreed. And I wasn't trying to be a smart-ass by bringing this up; just suggesting that a hard-line prohibition against changing class variables in a multi-threaded situation might be slightly excessive.
    Jeff Verdegan
    Bartender

    Joined: Jan 03, 2004
    Posts: 6109
        
        6

    Terry Tucker wrote:

    The simple program above increments a class variable (static variable) 10 million times. I have a shell script that runs this program in the background twice. They should be stomping on one another in this scenario if what I have been told regarding static variables is correct. I am simply trying to demonstrate the problem and am unable to do so. Is my test invalid?

    Thanks...


    There are a couple of mistaken assumptions here.

    1) Rules about shared variables and multithreading are no different for class (static) variables than for instance (non-static) variables.

    2) Each invocation of the JVM has its own memory, independent from any others. Class variables are only shared across instances in the same JVM. (Actually in the same classloader.) Since you're starting two separate processes, there's no chance of them seeing each others' variables.

    3) Even if you did this test in a single JVM with multiple threads, it's not that they should stomp all over each other, but rather that they can. Threads are not required to use local copies of shared variables, and they're not required to be scheduled in such a way that lack of syncing will cause undesired results, but that can happen That's what makes testing multithreaded code so difficult. It can behave correctly through billions of invocations, and then one time, the context and timing is just right and it fails.
    Stevens Miller
    Ranch Hand

    Joined: Jul 26, 2012
    Posts: 523
        
        3

    Terry Tucker wrote:

    The simple program above increments a class variable (static variable) 10 million times. I have a shell script that runs this program in the background twice. They should be stomping on one another in this scenario if what I have been told regarding static variables is correct. I am simply trying to demonstrate the problem and am unable to do so. Is my test invalid?

    Thanks...


    Terry, by starting up the program twice, you are running two processes, each of which has its own context and, therefore, its own address space. Junilu's point about multi-threading applies to a single process, where all threads run in the same address space.

    It's not that your test is invalid; it's that your test isn't testing what you think its. It's testing the independence of multiple processes. To see the effect we're talking about, you need to run your loop in one process, but in two (or more) threads.
    Stevens Miller
    Ranch Hand

    Joined: Jul 26, 2012
    Posts: 523
        
        3

    Jeff Verdegan wrote:...it's not that they should stomp all over each other, but rather that they can. Threads are not required to use local copies of shared variables, and they're not required to be scheduled in such a way that lack of syncing will cause undesired results, but that can happen That's what makes testing multithreaded code so difficult. It can behave correctly through billions of invocations, and then one time, the context and timing is just right and it fails.


    Man, I can testify to the truth of that!
    Jeff Verdegan
    Bartender

    Joined: Jan 03, 2004
    Posts: 6109
        
        6

    Stevens Miller wrote:
    Jeff Verdegan wrote:
    It's true that volatile != synchronized, but anything that's done with volatile can also be done with synchronization. (The converse isn't true, however.)

    Well, not without engaging in a tedious exercise in computer science that would serve no useful purpose, anyway.


    Not sure what you're saying here. Is it the first half of my statement you're refuting or the second?

    If we're going to use it as a stop flag, then we have to do one of the following, to ensure that all threads see our write:

  • Make it volatile.
  • Synchronize all access to it.
  • Use an AtomicXxx or a CountdownLatch or other suitable approach from java.util.concurrent.


  • Agreed. And I wasn't trying to be a smart-ass by bringing this up;

    Understood. My comments were aimed at just making sure everyone was on the same page, since the previous couple of posts could have led to some ambiguity.

    just suggesting that a hard-line prohibition against changing class variables in a multi-threaded situation might be slightly excessive.


    I hadn't realized such a stance had even been presented.
    Terry Tucker
    Greenhorn

    Joined: Jan 21, 2013
    Posts: 22

    Ranch Hands:

    I appreciate your answers on this. I don't think the fellow that was trying to explain to me why I should not do what I was doing didn't quite understand it himself; or, I may have simply missed his point. There is obviously a lot I have to learn about the Java VM and threads.

    Again, thanks for the help...
    Stevens Miller
    Ranch Hand

    Joined: Jul 26, 2012
    Posts: 523
        
        3

    Jeff Verdegan wrote:
    Stevens Miller wrote:
    Jeff Verdegan wrote:
    It's true that volatile != synchronized, but anything that's done with volatile can also be done with synchronization. (The converse isn't true, however.)

    Well, not without engaging in a tedious exercise in computer science that would serve no useful purpose, anyway.

    Not sure what you're saying here. Is it the first half of my statement you're refuting or the second?

    The second. Synchronization can be achieved with reliable shared memory (volatiles, in Java), but no one would do it that way.

    Actually, since Java lacks explicit memory fences, maybe even that's not true. (I am mostly remembering a single lecture I sat through in graduate school, about 25 years ago, where this issue came up. The point was that one can implement a mutex without support for it built into a language or an OS, but it's such a dreary undertaking that no modern OS lacks for such built-in support).

    just suggesting that a hard-line prohibition against changing class variables in a multi-threaded situation might be slightly excessive.

    I hadn't realized such a stance had even been presented.

    I was responding to this:
    ...there should be no way to change these variables at any time after they are initialized.

    Stevens Miller
    Ranch Hand

    Joined: Jul 26, 2012
    Posts: 523
        
        3

    Terry Tucker wrote:Ranch Hands:

    I appreciate your answers on this. I don't think the fellow that was trying to explain to me why I should not do what I was doing didn't quite understand it himself; or, I may have simply missed his point. There is obviously a lot I have to learn about the Java VM and threads.

    Again, thanks for the help...


    Brother, hang onto your seat. Learning to write multi-threaded code is like playing Whack-a-Mole with a blindfold on; you know never know where the next problem will pop up, nor are you always even sure where it came from once it does.

    But, it's worth it and, when you get it nailed, what you can do with it is way cool.
    Jeff Verdegan
    Bartender

    Joined: Jan 03, 2004
    Posts: 6109
        
        6

    Stevens Miller wrote:Synchronization can be achieved with reliable shared memory (volatiles, in Java), but no one would do it that way.


    No, it can't. For general atomicity, we need an atomic test-and-set operation. This is not achievable simply by using synchronized variables.


    just suggesting that a hard-line prohibition against changing class variables in a multi-threaded situation might be slightly excessive.

    I hadn't realized such a stance had even been presented.

    I was responding to this:
    ...there should be no way to change these variables at any time after they are initialized.



    Oh, right. Yeah, I disagree with that prohibition. It's perfectly acceptable to modify static variables in a multithreaded context, as long as we handle it properly. No different from instance variables.
    Stevens Miller
    Ranch Hand

    Joined: Jul 26, 2012
    Posts: 523
        
        3

    Jeff Verdegan wrote:
    Stevens Miller wrote:Synchronization can be achieved with reliable shared memory (volatiles, in Java), but no one would do it that way.

    No, it can't. For general atomicity, we need an atomic test-and-set operation. This is not achievable simply by using synchronized variables.

    Try Googling "Dekker's Algorithm." Maybe we're not thinking of the same thing, but that's a pure-software implementation of a mutex.
    Jeff Verdegan
    Bartender

    Joined: Jan 03, 2004
    Posts: 6109
        
        6

    Stevens Miller wrote:
    Jeff Verdegan wrote:
    Stevens Miller wrote:Synchronization can be achieved with reliable shared memory (volatiles, in Java), but no one would do it that way.

    No, it can't. For general atomicity, we need an atomic test-and-set operation. This is not achievable simply by using synchronized variables.

    Try Googling "Dekker's Algorithm." Maybe we're not thinking of the same thing, but that's a pure-software implementation of a mutex.


    Ah, cool. You learn something new every day.
    Stevens Miller
    Ranch Hand

    Joined: Jul 26, 2012
    Posts: 523
        
        3

    Jeff Verdegan wrote:
    Ah, cool. You learn something new every day.

    That's the whole reason I come here!
     
    With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
     
    subject: Use of Class Variables
     
    Similar Threads
    Transactions and Threading
    DB connection from servlets
    Why declare variables static
    Strings are poor substitutes for capabilities
    Still having some trouble with Observer/Observable