Is volatile keyword necessary?

H

Harald Kirsch

Consider the following code taken from
one and the same class declaring a field
and two methods.

// a field of the class
private volatile boolean done;

void method1() {
done = false;
synchronized(someObject) {
while(!done) someObject.wait();
}
}

void method2()
synchronized(someObject) {
done = true;
someObject.notifyAll();
}
}

I have two questions:
1) is the `volatile' keyword necessary to make sure
that method1() never finds an outdated value when
returning from wait().
2) Does the single call to notifyAll() guarantee that
method1() will eventually return from wait(), even if
other threads are either waiting on the same monitor or
are blocked by that monitor?


Thanks,
Harald Kirsch.
 
J

Jon Skeet

Harald Kirsch said:
Consider the following code taken from
one and the same class declaring a field
and two methods.

// a field of the class
private volatile boolean done;

void method1() {
done = false;
synchronized(someObject) {
while(!done) someObject.wait();
}
}

void method2()
synchronized(someObject) {
done = true;
someObject.notifyAll();
}
}

I have two questions:
1) is the `volatile' keyword necessary to make sure
that method1() never finds an outdated value when
returning from wait().

No - because it regains the monitor when it comes out of wait(), and
the act of regaining the monitor acts as a read memory barrier.
2) Does the single call to notifyAll() guarantee that
method1() will eventually return from wait(), even if
other threads are either waiting on the same monitor or
are blocked by that monitor?

It won't return from wait() if another thread which is also waiting
resumes and never releases the monitor...
 
C

Chris Uppal

Harald said:
void method1() {
done = false;
synchronized(someObject) {
while(!done) someObject.wait();
}
}

Did you mean to write:

void method1() {
synchronized(someObject) {
done = false;
while(!done) someObject.wait();
}
}

i.e, with the assignment to done *inside* the synchronized block ? If so then
I agree with what Jon Skeet has already posted, and please ignore the rest of
this message ;-)

If not then I don't think the code's doing what is intended; consider the
following sequence of events (this doesn't depend on the subtle semantics of
memory barriers):

<best viewed in mono-spaced font>

Thread1 in method1() | Thread2 in method2()
---------------------------------------------
| <enter monitor>
| done = true;
done = false; |
| someObject.notifyAll();
| <leave monitor>
<enter monitor> | <go do something else>
while (!done) |
wait(); |

</best viewed in mono-spaced font>

Thread1 will never wake up from the wait() unless some other thread executes
method2() a second time, which should not have been necessary.

-- chris
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top