Reputation:
public class Stuff {
private final Timer timer = new Timer(true);
public static final int DEFAULT_TIMEOUT = 1500;
private volatile int timeout = DEFAULT_TIMEOUT;
public void doStuff(OtherStuff) {
...
timer.schedule(timeout, ...);
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public int getTimeout() {
return timeout;
}
}
Instances of this class is accessed from just 1 thread, except the timeout variable which can be altered from another class. In my case a JMX bean, which means one can alter the timeout during runtime from a management interface.
The doStuff() could be running 100's of times/second, while the setTimeout() could be run once a week - so the ordering between someone doing setTimeout() and someone doing doWork() is not important.
Is making timeout
volatile sufficient for such a case ? Will the memory model guarantee that setting this from one thread to be visible to the doStuff()
method ?
Another alternative that seems safe would simply be:
public class Stuff {
private final Timer timer = new Timer(true);
public static final int DEFAULT_TIMEOUT = 1500;
private int timeout = DEFAULT_TIMEOUT;
public void doStuff(OtherStuff) {
...
timer.schedule(getTimeout(), ...);
}
public void synchronized setTimeout(int timeout) {
this.timeout = timeout;
}
public int synchronized getTimeout() {
return timeout;
}
}
Which of these 2 approaches would be preferred ?
Upvotes: 4
Views: 1050
Reputation: 3461
Despite both the approaches of the example are equivalent I think (because of the generality of the question) it's worth to talk about this:
The visibility effects of volatile variables extend beyond the value of the volatile variable itself. If the question was "will volatile also guarantee visibility of the same volatile variable?". The answer is yes.
But there is no guarantee visibility of the (if there are) other variables that are used before the writing on this variable.
From Full volatile Visibility Guarantee.
Example:
When thread A writes to a volatile variable and subsequently thread B reads that same variable, the values of ALL variables that were visible to A prior to writing to the volatile variable become visible to B AFTER reading the volatile variable.
Upvotes: 1
Reputation: 328568
From a visibility perspective, both approaches are equivalent. Any read on a volatile that happens subsequently to a write on that same volatile variable is guaranteed to see the write.
So if one thread writes timeout = newValue;
, any other threads subsequently calling timer.schedule(timeout)
is guaranteed to see newValue
.
This guarantee is specified in the JLS 17.4.5:
A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.
I would simply use volatile as the guarantees it provides are sufficient and it clearly shows your intent.
Upvotes: 7