I have an atomic boolean property in Java
private AtomicBoolean endOfInputDataSet;
What are the proper getter and setter of this property and what are the consequences of each choice? I can return the AtomicBoolean
directly
public AtomicBoolean getEndOfInputDataSet() {
return this.endOfInputDataSet;
}
public void setEndOfInputDataSet(AtomicBoolean endOfInputDataSet) {
this.endOfInputDataSet = endOfInputDataSet;
}
or I can return the unwrapped boolean
:
public boolean getEndOfInputDataSet() {
return this.endOfInputDataSet.get();
}
public void setEndOfInputDataSet(boolean endOfInputDataSet) {
this.endOfInputDataSet.set(endOfInputDataSet);
}
I think the latter solution is just simpler for using by the client and cleaner, but why is it not default when IntelliJ generates the getter and setter?
šš½ Share the Atomicā¦
object container, not its payload value.
public final AtomicBoolean endOfInputDataSet = new AtomicBoolean( false ) ;
AtomicBoolean
objectFor multiple threads to coordinate around the value contained in the payload of an Atomicā¦
object, the threads must have simultaneous direct access to the Atomicā¦
object itself.
AtomicBoolean
Emitting copies of the value to the various threads breaks the atomic nature of the interaction intended by use of Atomicā¦
class. Making copies of the payloadās value is not thread-safe, with the threads now unable to coordinate around a single value.
private AtomicBoolean endOfInputDataSet;
Make that final
to prevent another AtomicBoolean
object from being assigned to replace the original.
And you might as well instantiate in the declaration.
private final AtomicBoolean endOfInputDataSet = new AtomicBoolean( ā¦ ) ;
return this.endOfInputDataSet;
The Atomicā¦ objects are containers that carry a payload while providing thread-safe access to that payload.
This line returns a reference to that container. The calling programmer may then get or set the content of that payload.
this.endOfInputDataSet = endOfInputDataSet;
This line ruins your scenario. You enable the calling programmer to replace your container.
return this.endOfInputDataSet.get();
This line returns a copy of the content of your container.
Be aware that this lineās method is returning āold newsā. There is a beat of time between the end of the get()
call and the moment when the calling programmer actually receives the value. During that beat, another thread may have executed a set
on the atomic container, changing the content of the container. You have undone the āAtomicā in AtomicBoolean
. This code is not thread-safe.
And there are further beats of time between (a) the calling method receiving our returned copy of the payloadās value and (b) the calling method making use of that value. During these additional beats the calling actual payload in the AtomicBoolean
object could be changing.
this.endOfInputDataSet.set(endOfInputDataSet);
This line is non-atomic and thread-unsafe in the same way as the line above it.
why is it not default when IntelliJ generates the getter and setter?
Because such code is not thread-safe.
When trying to coordinate multiple threads around a single value, those threads must all be dealing simultaneously with the very same value, the value carried as the payload within the atomic wrapper. To accomplish that, all the threads must be dealing with the atomic wrapper container directly.
So, you donāt really need getter/setter accessor methods here. Just make the atomic object final
and directly accessible (public
etc.).
Think of a bunch of kids in a classroom trying to coordinate their activity around a message in an envelope. If you let various kids copy that message while other kids are changing the message, you have chaos. To coordinate the kidsā activity, they must be simultaneously viewing the one and only message carried in that envelope.