Threads and synchronization


S

Srubys

hiya

1. Why do all the statements in constructor execute prior to
statement “ new Thread(this).start();” , even if “new
Thread(this).start();” precedes the other statements? For example:

class A {
int i = 100;
A(){
new Thread( this ).start();
i++; // i will have value of 101 before new
thread is
started, even though i++ follows the
statement that creates a new thread
}



2. While a thread is inside a synchronized method, all other threads
that try to call any synchronized methods on the same instance have to
wait.

So if for example process has 3 threads ( A, B and C) and A calls some
synchronized method on object D, and while A is still inside D, B and
C also call method on same object. While A is still inside D, will
context switching still happen, even if B and C won’t do anything due
to waiting on thread A to exit the monitor?



3.After experimenting with a code a bit, I came to conclusion that
when a thread enters a synchronized block, all other threads trying to
enter synchronized block on same instance will have to wait until this
thread exits the synchronized block. So, if we again have threads A,
B and C and if thread A enters object’s monitor via synchronized
block:

synchronized( object ) {

for( int i = 0; I < 1000000; i++ );
}

then A will get ahold of object’s monitor even if no methods are
called on that object inside the synchronized block. And B and C won’t
be able to enter synchronized block until A exits the synchronized
block? Right?

BTW – why does infinite for() loop inside synchronized block cause
compile time error?



4. If we again have threads A, B and C and if thread A enters
object’s monitor and then calls notify(), then a thread that called
wait() on the same object is awakened:

• but what if B and C are trying to get ahold of object’s
monitor, but didn’t call wait()? Will they still get notified
via
notify()?
• if thread A calls wait(); but if then none of the threads that
afterwards enter same object’s monitor ever call notify(),
will A ever get awaken or will it always remain in a wait
state?


thank you
 
Ad

Advertisements

A

Arne Vajhøj

1. Why do all the statements in constructor execute prior to
statement “ new Thread(this).start();” , even if “new
Thread(this).start();” precedes the other statements? For example:

class A {
int i = 100;
A(){
new Thread( this ).start();
i++; // i will have value of 101 before new
thread is
started, even though i++ follows the
statement that creates a new thread
}

I believe instance members are instantiated before constructor
statements.

And you should not use this in the constructor !
2. While a thread is inside a synchronized method, all other threads
that try to call any synchronized methods on the same instance have to
wait.

So if for example process has 3 threads ( A, B and C) and A calls some
synchronized method on object D, and while A is still inside D, B and
C also call method on same object. While A is still inside D, will
context switching still happen, even if B and C won’t do anything due
to waiting on thread A to exit the monitor?

I think that is implementation specific.
3.After experimenting with a code a bit, I came to conclusion that
when a thread enters a synchronized block, all other threads trying to
enter synchronized block on same instance will have to wait until this
thread exits the synchronized block. So, if we again have threads A,
B and C and if thread A enters object’s monitor via synchronized
block:

synchronized( object ) {

for( int i = 0; I < 1000000; i++ );
}

then A will get ahold of object’s monitor even if no methods are
called on that object inside the synchronized block. And B and C won’t
be able to enter synchronized block until A exits the synchronized
block? Right?
Yes.

4. If we again have threads A, B and C and if thread A enters
object’s monitor and then calls notify(), then a thread that called
wait() on the same object is awakened:

• but what if B and C are trying to get ahold of object’s
monitor, but didn’t call wait()? Will they still get notified
via
notify()?

No. What should notification mean ?
• if thread A calls wait(); but if then none of the threads that
afterwards enter same object’s monitor ever call notify(),
will A ever get awaken or will it always remain in a wait
state?

It will remain unless you the one the version with timeout.

I think - I have never tried it.

Arne
 
M

Mark Space

Arne said:
I believe instance members are instantiated before constructor
statements.

And you should not use this in the constructor !


I think that is implementation specific.


No. What should notification mean ?


It will remain unless you the one the version with timeout.

I think - I have never tried it.

Arne
 
M

Mark Space

Arne said:
I believe instance members are instantiated before constructor
statements.

I'm not following how this bears on the OP's question. For the OP: I
don't think "i" will always have the value 101 before the new thread is
started. You have a race condition here. "i" might have the value 100,
101, or it could even be in the middle of changing fro 100 to 101.
And you should not use this in the constructor !

True! Do you see what he means Sruby? You've give an object ("Thread"
here) a pointer to your object A, but you aren't even done making the
object yet. It's incomplete. In your simple example this wont matter,
but many times it will (and sometimes in surprising ways when you get
into synchronizing object creation between threads). Never never
publish a this pointer from a constructor.

I think that is implementation specific.

What Arne means here is "it depends." D might be able to context
switch, or it might not. You have to assume whatever is the worst for
your application and code for that problem.

I think the rest of Arne answers are easy to understand but I'm still
kinda confused by the first one.
 
A

Arne Vajhøj

Mark said:
I'm not following how this bears on the OP's question. For the OP: I
don't think "i" will always have the value 101 before the new thread is
started. You have a race condition here. "i" might have the value 100,
101, or it could even be in the middle of changing fro 100 to 101.

No. I believe that the Java standard specify that instance members
instantiation (int i = 100;) happen before constructor statements
(i++;).

http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.5

(point 4 and 5)
I think the rest of Arne answers are easy to understand but I'm still
kinda confused by the first one.

Maybe I am just babbling ...

Arne
 
P

Patricia Shanahan

hiya

1. Why do all the statements in constructor execute prior to
statement “ new Thread(this).start();” , even if “new
Thread(this).start();” precedes the other statements? For example:

class A {
int i = 100;
A(){
new Thread( this ).start();
i++; // i will have value of 101 before new
thread is
started, even though i++ follows the
statement that creates a new thread
}
....

I don't think you have any way to evaluate when the start() method
executes. More likely, you are looking at when the new thread executes
its run method.

That can happen at any time after the call to start. However, on a
single processor system it will usually be after the next few statements
in the currently running thread. There is a significant cost to
switching threads, so operating systems tend to let the current thread
go on running until it needs to wait for something or exhausts a time
slice. You might get different results on a multiprocessor, or under
high load conditions.

The issue is complicated by the question of memory visibility.
Especially on multiprocessors, threads may not see the results of
assignments in other threads instantly.

Given all those issues, I am reasonably sure the new thread will see i
as having one of three values: 0, 100, and 101, but I don't think it is
possible to predict which.

Patricia
 
Ad

Advertisements

M

Mark Space

Peter said:
Of course, the answer is that it _does_ execute before the increment
statement, but he simply misunderstands what the call to Thread.start()
does. In particular (as you and Mark know, but apparently the OP does

Hmmm... thinking out loud here... OTOH both the compiler and the JVM are
allowed to re-order statements if the result is the same. Could that
also been happening here?

(Emphasis on the word *also*... the OP clearly has a race condition, but
it could be made worse by the way the compiler writes the byte codes.

In fact, there shouldn't be any access at all of a partially constructed
object's fields, so the "i", even though public to the package, should
not be accessed while the object is constructing. Therefore, the
compiler could optimize it with a single write of 101 and ignore the
"i++" statement. Of course, it also might not, so the potential for a
race condition remains.)
 
N

Neil Coffey

Patricia said:
Given all those issues, I am reasonably sure the new thread will see i
as having one of three values: 0, 100, and 101, but I don't think it is
possible to predict which.

And of course, you shouldn't *care* which it sees with the current
code. If you want another thread to see the variable, then you have
to manipulate it in a thread-safe manner.

Neil
 
J

Joshua Cranmer

Mark said:
Hmmm... thinking out loud here... OTOH both the compiler and the JVM are
allowed to re-order statements if the result is the same. Could that
also been happening here?

I've not been reading this thread in detail, and nor am I an expert on
the thread model of the JLS (by far the densest part, IMHO), but from
what I understand, this is what happens:

Let us define several events.
Event A: i is set to default value (0).
Event B: i is set to 100 by (implicit) constructor
Event C: New thread is created
Event D: i is read from in constructor
Event E: i is written to in constructor as value+1
Event F: i is hypothetically read from in new thread.

Thread 1 is the thread invoking the constructor, Thread 2 is the created
thread.

On thread 1, clearly, the happens-before order is:
A -> B -> C -> D -> E
On thread 2, clearly, the happens-before order is:
C -> F

Applying synchronization actions, we find that C is synchronized-with F,
so the two graphs can be merged on C.

Therefore, we can conclude that E and F have no ordering and constitute
a data race, while no other combination of reads or writes constitute a
data race.

So, assuming thread 2 doesn't write to i, event F can only see the
values of 100 or 101 for i.

Also in short, we can assume that the permissible reorderings do not
include the inversion of |i++;| and the thread creation.

Final note on this point: I have not studied this sufficiently enough to
be fully authoritative on this topic. You may have different
interpretations of JLS 3 §§17.4.1-4.
(Emphasis on the word *also*... the OP clearly has a race condition, but
it could be made worse by the way the compiler writes the byte codes.

Not the bytecode (which is highly specified), but the JIT assembly.
In fact, there shouldn't be any access at all of a partially constructed
object's fields, so the "i", even though public to the package, should
not be accessed while the object is constructing. Therefore, the
compiler could optimize it with a single write of 101 and ignore the
"i++" statement. Of course, it also might not, so the potential for a
race condition remains.)

The best way to sum it all up is, as said before, "don't let |this|
escape a constructor..." including, especially, virtual functions.
 
P

Patricia Shanahan

Even if the compiler and JVM keep everything in order, there can still
be memory order issues, especially on a multiprocessor. Maintaining full
sequential consistency between caches can be *very* expensive and
inefficient. Only depend on what the JLS promises.
I've not been reading this thread in detail, and nor am I an expert on
the thread model of the JLS (by far the densest part, IMHO), but from
what I understand, this is what happens:

Let us define several events.
Event A: i is set to default value (0).
Event B: i is set to 100 by (implicit) constructor
Event C: New thread is created
Event D: i is read from in constructor
Event E: i is written to in constructor as value+1
Event F: i is hypothetically read from in new thread.

Thread 1 is the thread invoking the constructor, Thread 2 is the created
thread.

On thread 1, clearly, the happens-before order is:
A -> B -> C -> D -> E
On thread 2, clearly, the happens-before order is:
C -> F

Applying synchronization actions, we find that C is synchronized-with F,
so the two graphs can be merged on C.

I agree with this reasoning, and withdraw the claim that 0 is a possible
value for i, reducing the set of possible values to {100,101}.

Patricia
 
S

Srubys

Of course, the answer is that it _does_ execute before the
increment statement, but he simply misunderstands what the call to
Thread.start()does. In particular (as you and Mark know, but
apparently the OP does not), calling Thread.start() simply makes >the newly-created Thread instance runnable. He just isn't
comprehending what Thread.start() actually does.

Uh, you’re talking about me as if I was Forrest Gump. On the other
hand, the answer is pretty obvious and I should know it… chocolate
anyone?


May I ask one more question - Could someone tell me why infinite for()
loop inside synchronized block causes compile time error? Why would
only main thread be allowed to have an infinite loop?


Thank you all for your input
 
Ad

Advertisements

J

Joshua Cranmer

BTW – why does infinite for() loop inside synchronized block cause
compile time error?

What's your actual code? The following works for me:

class test {
public static void main(String... args) {
synchronized(args) {
for (;;) {
}
}
}
}
 
M

Mark Space

Peter said:
There's no guarantee to the compiler that "i" isn't accessed outside the
constructor before the constructor completes. In fact, this particular

Really? I'm not trying to be argumentative here, just thinking about
how Java actually works.

A a = new A();

There's two things that happen here. First the call to the default
constructor of class A, then the assignment to the variable "a".
There's no way, even in a multi-threaded application, that "a" can be
accessed until it's assigned a reference. Even like this:

int i = new A().someField();

first A has to be constructed, fully, then it's field can be accessed.
If this code is execute by two threads, you have two objects, not two
threads accessing one object. You have the same in the first example,
until a is assigned a reference, and even then if a is local then you
still have two separate objects.

The only exception is of course publishing a reference to a reference to
a partially constructed object, and we all know that's bad. But it's
also not "normal" and I'm thinking that Java might optimize what is
prescribed, and ignore what is proscribed.
 
P

Patricia Shanahan

Peter said:
On Tue, 24 Jun 2008 18:59:02 -0700, Mark Space


There's no guarantee to the compiler that "i" isn't accessed outside the
constructor before the constructor completes. In fact, this particular
example is exactly the sort of thing that illustrates why that's so.
Since a compiler is responsible for generating logically correct code,
and not for making assumptions that the coder has followed some
desirable convention, the compiler doesn't have the ability to optimize
out the increment.
....

"i" is not volatile and there is no action between the initialization
and the increment that would ensure an action in the new thread
"happens-before" the increment to 101.

Accordingly, there is no guarantee that it is possible for another
thread to see the 100 value, and no need for the compiler to make it
possible.

Patricia
 
P

Patricia Shanahan

Peter Duniho wrote:
....
If the Java compiler were allowed to assume that instance members
wouldn't be accessed until after the object was constructed except from
within the constructor itself, the language would make it an error to
allow the object reference to be passed out of the constructor.
Obviously, Java doesn't do that (and thank goodness, as there are lots
of valid kinds of code that would be prevented if it did) and so I
really don't believe that the compiler is going to make the assumption
that the reference isn't visible outside the constructor (well, it might
if the constructor never passes it to some other method...but that
wouldn't apply here).
....

There are two distinct cases to consider, intra-thread and inter-thread.

Within a thread, every operation happens-before any operation in the
same thread that is later in program order. If there were a call from
the constructor to a method that accessed i in the same thread between
initialization and increment, the method *must* see i==100, not i==101.

On the other hand, the specific issue is code in a different thread. The
sample code had no calls other than the thread start call, which does
not access any local variables in the same thread. The JLS has very
specific rules about what ordering is required between threads. I don't
see any of those rules as requiring any other thread to ever see i==100.

Patricia
 
L

Lew

Peter Duniho said:
"All this focus" is because I was responding to a very specific point: the  
suggestion that the compiler might optimize out the initialization of 100..

Oh, no wonder I didn't understand. It was so patently obvious that
the compiler could not do that, since it's a run-time issue, that that
was the source of my confusion. I just couldn't see what there was
controversial in your claim.
I appreciate that you finally concluded (well, guessed, anyway) that I was  
correct.  But none of the rest of what you wrote was being debated.  We  
all agree on those points (and now on mine as well, as near as I can tell  
:) ).

I completely did not understand what the fuss was about, since it's so
blindingly obvious that the compiler could not "optimize" away the
initialization to 100. If none of the "rest of what wrote was
being debated", then it would have been obvious to everyone, since
what I wrote was precisely why the compiler cannot suppress the value
of 100.
 
Ad

Advertisements

L

Lasse Reichstein Nielsen

Lew said:
The OP wrote (// comments added and class name enhanced, SSCCEified):
class WrongThreader implements Runnable
{
int i = 100;
WrongThreader()
{
new Thread( this ).start(); // antipattern
i++; // n.b., post-increment is not atomic
}
public void run()
{
System.out.println( "i = ", i );
}
public static void main( String [] args )
{
new WrongThreader();
}
The compiler cannot guarantee that the second thread will see 100 or
101.

Or 0.

/L :)
 
J

Joshua Cranmer

Lasse said:
Lew said:
The OP wrote (// comments added and class name enhanced, SSCCEified):
class WrongThreader implements Runnable
{
int i = 100;
WrongThreader()
{
new Thread( this ).start(); // antipattern
i++; // n.b., post-increment is not atomic
}
public void run()
{
System.out.println( "i = ", i );
}
public static void main( String [] args )
{
new WrongThreader();
}
The compiler cannot guarantee that the second thread will see 100 or
101.

Or 0.

/L :)

How could it see 0? See
 
P

Patricia Shanahan

Lew said:
Oh, no wonder I didn't understand. It was so patently obvious that
the compiler could not do that, since it's a run-time issue, that that
was the source of my confusion. I just couldn't see what there was
controversial in your claim.

I'm afraid that sub-thread was my fault. Despite it's patent
obviousness, I didn't get the point until Peter explained it, because I
was too focused on Thread's start() method as starting a new thread,
rather than on it as a method that *might* call something that accesses
i in the current thread.

Apologies for denseness.

Patricia
 
Ad

Advertisements

L

Lasse Reichstein Nielsen

Joshua Cranmer said:
Lasse said:
Lew said:
The OP wrote (// comments added and class name enhanced, SSCCEified):

class WrongThreader
implements Runnable
{
int i = 100;
WrongThreader()
{
new Thread( this ).start(); // antipattern
i++; // n.b., post-increment is not atomic
}
public void run()
{
System.out.println( "i = ", i );
}
public static void main( String [] args )
{
new WrongThreader();
}
}
The compiler cannot guarantee that the second thread will see 100 or
101.
Or 0.
/L :)

How could it see 0? See news:[email protected]


The class has int field called "i". As an int field, its initial value
is zero, and it is not set to 100 until after the superclass' constructor
has run. That would be Object's default constructor, which doesn't do
a lot, but it's there.
I.e., at some point the value is zero.

The other thread, when started, accesses the value of the field from a
different thread than where it was assigned the values 100 and 101,
without any synchronization. Therefore the other thread should also
be able to see the stale value "0".

/L
 

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

Top