0

I have a global variable and multiple threads which are consistently reading the variable every few seconds.

Now I have a method in one thread which writes to the variable, and when I print out the global variable within the function where I am writing to it, I see the write has taken place and the variable value is changed as desired.

But when I read from outside the scope of the function immediately after it executes, the global variable has in fact not changed, and the write has not been successful.

Does it sound like this is due to simultaneous read/write? I'm thinking there is something going on I don't understand, though intuitively I can't see how multithreading would change anything as the global variable is being changed at least momentarily.

No writes are happening other than the one mentioned.

I haven't read up on multithreading too much so I just want a high-level "yes this is possible and makes sense with multithreading and global variables" and I will read up as necessary.

Alex
  • 325
  • 7
  • 16
  • 1
    Without seeing any code, any guess is possible. Also: there are no global variables in Java. Maybe that's part of why it doesn't perform as you expect. Can you explain what exactly you mean with 'global variable' ? – Stultuske Dec 02 '15 at 13:30
  • member variable of a class available to all nested class – Alex Dec 02 '15 at 13:31
  • if it's a static member, another call through another instance would change the value – Stultuske Dec 02 '15 at 13:34
  • The answer is: yes this is possible and makes sense with multithreading and shared variables. Multithreading can be quite hard to get right so I would not start creating threads here and there without understanding at least [the basics](https://docs.oracle.com/javase/tutorial/essential/concurrency/)... See for example: [Memory consistency errors](https://docs.oracle.com/javase/tutorial/essential/concurrency/memconsist.html). – assylias Dec 02 '15 at 13:34
  • @Stultuske, Depends what you mean by "global". One meaning of "global variable" is a variable that is in-scope everywhere. A public class variable `bar` of a public class `Foo` is in-scope everywhere... You can access it's value from anywhere, even though outside the class `Foo`, you have to use its full name, `Foo.bar`, while within the `Foo` class itself, you can just say `bar`. – Solomon Slow Dec 02 '15 at 15:13
  • @jameslarge: that's a very ... shortsighted version of global. as long as the class isn't instantiated, that variable doesn't exist. global means always and everywhere accessible. even static variables aren't completely 'global' as the definition of global stands. instance variables, even when declared public even less – Stultuske Dec 02 '15 at 17:53
  • @Stultuske, Yeah, you're right. You could use class loaders to create a program in which different uses of the same, fully qualified, `com.whatever.Foo.bar` refer to different variables. I'll stand by my definition though. I can't think of a better way to explain "global variable" except to say, it's a variable that is in-scope everywhere. I think what you're telling me is that if I don't do class loader tricks, then my `com.whatever.Foo.bar` is only _effectively_ global. I can live with that. – Solomon Slow Dec 02 '15 at 18:53

3 Answers3

0

Without seeing the actual code I can smell the problem, just use volatile in front of your global static variable and see the magic. Problem solved.

More information can be found at Volatile vs static

Community
  • 1
  • 1
Deepak Bhatia
  • 6,230
  • 2
  • 24
  • 58
  • That may or may not be enough. If he is using a setter then making the variable volatile won't make any difference... – assylias Dec 02 '15 at 13:35
  • I am just guessing the most probable problem that occurs while accessing a variable across multi-threaded program and as @Alex mentioned `No writes are happening other than the one mentioned` it means only one write is happening. – Deepak Bhatia Dec 02 '15 at 13:38
0

Are you sure you don't have two variables with the same name?

I print out the global variable within the function where I am writing to it, I see the write has taken place...But when I read from outside the scope ... the global variable has in fact not changed.

That's what I would expect if your function declared a local variable with a name that shadows the global.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57
-1

You should declare your variable as volatile as well as synchronize access to it. The following code is an example to prevent collisions between threads to access myVariable.

public class ChangeVariable {
    static volatile int myVariable;
    static final Object lock = new Object();

    public static void setVariable(int value) {
        synchronized (lock) {
            myVariable = value;
        }
    }

    public static int getVariable() {
        synchronized (lock) {
            return myVariable;
        }
    }
}
cheshy
  • 179
  • 1
  • 4
  • The use of relying wholly on volatile can be risky because volatile can be platform dependent. – cheshy Dec 02 '15 at 14:00
  • 2
    Volatile has very specific semantics defined in the JLS and although some platforms may give "more safety" than required by the specifications, they can't give less... In particular, your example is ***guaranteed*** to be thread safe without the lock, ***on all platforms***. – assylias Dec 02 '15 at 14:07