Local variables in Java

A

ankur

So I was wondering how local variables are handled in Java. If the
same method is called upon many objects ( of same type) I guess the
method calls happen one after the another so that for each method call
new local variables get defined , but at any point in time there is
only one copy of all local variables defined ( while method calls are
happening). Correct ???

But then how would this work in a multicore system ( more than one
processor, same harddrive,same RAM) system if same method call is
executed by same JVM in parallel on the two cores for two different
objects ( of same class) ?



Ankur

Am I asking the right question ?? You get my point ?
 
L

Lew

ankur said:
So I was wondering how local variables are handled in Java. If the
same method is called upon many objects ( of same type) I guess the
method calls happen one after the another so that for each method call
new local variables get defined , but at any point in time there is
only one copy of all local variables defined ( while method calls are
happening). Correct ???

Not correct. Each invocation of the method, even if through the same object,
gets its own "stack frame". "Automatic variables", or "method-local
variables", the ones declared with method scope, are created specifically
within a particular stack frame. If objects are created for those variables
entirely within the method they will not collide.

If the method variables point to "wider" objects, such as those shared by the
class or between threads, there are issues of shared data.

Instance variables, the ones that belong to the whole object, are another
matter. As long as different objects are running their methods there is no
collision. In other words:

Foo a = new Foo();
Foo b = new Foo();
new Thread( a ).start();
new Thread( b ).start();

Even though both Foo objects are running their run() methods at the same time,
there is no collision between instance variables, because separate instances
are running.

However, if the /same/ instance is shared between threads, than any state
(values of its attributes) could collide.

Class variables, those declared 'static', have tremendous risk of collision,
because they are shared amongst all instances across all threads (within a
single ClassLoader context).

public class Foo implements Runnable
{
private static volatile Foo latestFoo;
public void run()
{
latestFoo = this;
doMore();
latestFoo.doEvenMore();
}
....
}
But then how would this work in a multicore system ( more than one
processor, same harddrive,same RAM) system if same method call is
executed by same JVM in parallel on the two cores for two different
objects ( of same class) ?

No problem unless both objects access shared data, as above. Shared data must
be protected by appropriate concurrency constructs.
 
J

Jim Korman

So I was wondering how local variables are handled in Java. If the
same method is called upon many objects ( of same type) I guess the
method calls happen one after the another so that for each method call
new local variables get defined , but at any point in time there is
only one copy of all local variables defined ( while method calls are
happening). Correct ???

No! Each invocation of the method gets its own "frame" containing its
own local variables.
But then how would this work in a multicore system ( more than one
processor, same harddrive,same RAM) system if same method call is
executed by same JVM in parallel on the two cores for two different
objects ( of same class) ?



Ankur

Am I asking the right question ?? You get my point ?

That's what synchronization is for.

Jim
 
J

John W. Kennedy

ankur said:
So I was wondering how local variables are handled in Java. If the
same method is called upon many objects ( of same type) I guess the
method calls happen one after the another so that for each method call
new local variables get defined , but at any point in time there is
only one copy of all local variables defined ( while method calls are
happening). Correct ???

But then how would this work in a multicore system ( more than one
processor, same harddrive,same RAM) system if same method call is
executed by same JVM in parallel on the two cores for two different
objects ( of same class) ?

Cores have nothing to do with it; threads do.
 
L

Lew

Jim said:
No! Each invocation of the method gets its own "frame" containing its
own local variables.

But beware, those local variables can be pointed to shared objects.

You'll be safe if the objects are created expressly for the method and within it:

public class Foo implements Runnable
{
public void run()
{
Bar bar = new Bar();
// etc.
}
}

Since 'bar = new Bar()' happens entirely "inside" the method, the reference
'bar' will vanish at the end of the method. If the reference hasn't been
shared with anyone else, then no one references that particular Bar any more.

The creation of that new Bar is completely independent no matter how many
threads within the Foo object are doing it, no matter how many Foo instances
are doing it. Each separate variable 'bar' is, as Jim Korman explained,
within the frame of the individual method invocation and not shared, and each
'new' is brand new to that method's frame.

However:

public class Fool implements Runnable
{
private Bar myBar = new Bar();
public void run()
{
Bar bar = myBar;
// etc.
}
}

This is a different situation. Even though the *variable* 'bar' is local to
the run() method, it points to the same 'Bar' instance as the variable
'myBar', and this instance is subject to influence by all users of a single
'Fool' instance. This is especially cause for attention in multi-threaded
scenarios.

So if that single 'Fool' instance in its run() method were to affect the
object that its method-local 'bar' variable points to, it would change the
same object as the instance variable 'myBar' points to.

By an inverse of this procedure:

public void run()
{
Bar bar = new Bar();
myBar = bar;
.... }

you have what is called an "escaping" reference. What starts as a "local"
object becomes known to the whole instance, or even via a static variable to
the whole class, or to another class, or to another thread. Even when the
'bar' reference goes out of scope, the 'myBar' reference continues to make the
'Bar' object reachable. If that same reference becomes visible outside the
thread that created it, it has "escaped the thread". You get both
synchronization and garbage collection consequences.

So in order to fully answer the original question, the safety of a variable
has to do with two things, the scope of the variable (block, method, instance,
class and how those intersect with threads), and the lifetime of the object.
Sometimes they match, sometimes they don't.

You could have a local variable point for a short time to a long-lived object
while it does something useful, much as a valet possesses your car for a
little while, or the object could be created for the lifetime of the variable
and no longer, as a car for the crash-test dummy.

You as the car's owner will have to synchronize with the valet if you want to
avoid problems with deciding who gets to drive. The crash-test dummy doesn't
need to worry about sharing his car object - it only lasts for the duration of
the run() method of the CrashTest class, and it gets no other drivers.

The same CrashTest lab can run multiple tests without worry - it creates a new
dummy and a new car for each run(). The valet has to drive many cars - he's
the variable that points to many different objects with each run(). There
could be a problem if many patrons show up at the premiere too quickly and he
cannot service all those cars at once.
 
L

Lew

John said:
Cores have nothing to do with it; threads do.

Cores do have an influence, at least in the transition from one to at least two.

Threads tend to be "synchronized by default" in a uniprocessor environment.
Some, and I emphasize only some, of concurrency's behind-biters show up with
more probability only when multiple cores are involved.

The reason is the memory model. Concurrency isn't just about race conditions
and deadlocks and the like, it's about when changes incurred in one thread are
visible in another. The rules for this are called Java's "memory model".

In multi-core systems, each thread likely operates with a thread-local memory
that lives entirely on the CPU's local cache or local memory. Without
synchronization, the system might not share memory changes across CPUs.

In a single-processor environment, multiple threads could "accidentally" share
the same copy of the data even if we forget to synchronize properly. I have
read that Java programs that evinced no threading issues in uniprocessor
environments experienced them when ported to multi-core platforms.

Note that even if such programs are run on uniprocessor systems without
apparent problems, that does not make them correct.
 
P

Patricia Shanahan

Lew wrote:
....
Cores do have an influence, at least in the transition from one to at
least two.

Threads tend to be "synchronized by default" in a uniprocessor
environment. Some, and I emphasize only some, of concurrency's
behind-biters show up with more probability only when multiple cores are
involved.

The reason is the memory model. Concurrency isn't just about race
conditions and deadlocks and the like, it's about when changes incurred
in one thread are visible in another. The rules for this are called
Java's "memory model".
....

In addition to memory model issues, a simple race condition can be more
likely on multiple processors, because of the loss of the "synchronized
by default" effect.

Patricia
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,058
Latest member
QQXCharlot

Latest Threads

Top