java - volatile keyword also for non-primitives - java

I am unsure if the volatile keyword should also be used for non-primitives. I have a class member which is set/assigned by one thread, and accessed by another thread. Should I declare this member volatile?
private /* volatile */ Object o;
public void setMember(Object o) {
this.o = o;
}
public Object getMember() {
return o;
}
Here, setMember(...) is called by one thread and getMember() is called by another one.
If it was a boolean, for example, the answer would be yes.
I am using Java 1.4 and the member in this case is read-only. So I am only caring about visibility in this case, hence my question about the volatile keyword.

Yes - volatile has exactly the same significance for reference-type fields that it has for primitive-type fields. Except that in the case of reference types, the members of the object the field refers to must also be designed for multi-threaded access.

You can, and it may be helpful, but remember the keyword just applies to the setting of the reference. It has no effect on multi-thread visibility of the properties inside that object. If it is stateful, you probably want to synchronize around each access to it anyway, to ensure the desired happens-before relationships.

Yes, your code is correct. In this case the reference itself is volatile, so chances to the reference are automatically visible in all other threads, but not changes to the object being referenced.

If we look up AtomicInteger class, it has declared value as volatile , So it can be used in multi-threaded environment without any thread cache issue.
public class AtomicInteger {
private volatile int value;
/**
* Gets the current value.
*
* #return the current value
*/
public final int get() {
return value;
}
/**
* Sets to the given value.
*
* #param newValue the new value
*/
public final void set(int newValue) {
value = newValue;
}
}
But if you think reference to AtomicInteger it shelf will be modified with different AtomicInteger objects by many threads; then you need volatile for that reference too.
private volatile AtomicInteger reference = new AtomicInteger(0);
Mostly it won't be the case; only value of the object will changed; hence declare it as final.
private final AtomicInteger reference = new AtomicInteger(0);

Related

Why are not volatile final fields permitted?

I'm designing a thread-safe container class called ConcurrentParamters. here is what I tend to write:
Interfaces:
public interface Parameters {
public <M> M getValue(ParameterMetaData<M> pmd);
public <M> void put(ParameterMetaData<M> p, M value);
public int size();
}
public interface ParameterMetaData<ValueType> {
public String getName();
}
Implementation:
public final class ConcurrentParameters implements Parameters{
private final Map<ParameterMetaData<?>, Object> parameters;
private final volatile AtomicInteger size; //1, Not compile
{
size = new AtomicInteger();
parameters = new ConcurrentHashMap<>();
}
public static Parameters emptyParameters(){
return new ConcurrentParameters();
}
#Override
public <M> M getValue(ParameterMetaData<M> pmd) {
M value = (M) parameters.get(pmd);
return value;
}
#Override
public <M> void put(ParameterMetaData<M> p, M value){
parameters.put(p, value);
size.incrementAndGet();
}
#Override
public int size() {
return size.intValue();
}
}
I tried to make the AtomicInteger field representing the size final, to ensure that no method can change the field poinitng to another object, as well as initialize it duriong consruction.
But since the container will be accessed concurrently, I need that any thread observes changes made by other. So, I tried to declared it volatile as well in order ot avoid unnecessary synchronization (I don't need mutual-exclusion).
I didn't compile. Why? Is there any reason? Does it make no sense to decalre a field that way? I thought it would be sesnsible... Maybe it is inheritly not safe?
The answer is simple:
All guarantees volatile makes, are done by final already. So it would be redundant.
Take a look at the answer here from axtavt for more detailed information:
Java concurrency: is final field (initialized in constructor) thread-safe?
volatile means that reads and writes to the field have specific synchronization effects; if you cannot write to the field, volatile makes no sense, so marking a field final volatile is forbidden.
You don't need volatile, and it wouldn't help. Mutations to an AtomicInteger are not assignments to the field that holds the AtomicInteger, so they wouldn't be affected by volatile anyway. Instead, reads and modifications of an AtomicInteger's value already have the appropriate thread-safety mechanisms applied by the AtomicInteger implementation itself.
A volatile variable means that it may be accessed by unsynchronized threads so its value should always be written back to memory after each and every change to it. But then again, you can't change a variable declared as final, thus volatile is irrelevant in your example.

Is double check with final variable working

I have class designed for lazy initialization and storing objects which creation is not necessary threadsafe. Here is the code:
class SyncTest {
private static final Object NOT_INITIALIZED = new Object();
private Object object;
/**
* It's guaranteed by outer code that creation of this object is thread safe
* */
public SyncTest() {
object = NOT_INITIALIZED;
}
public Object getObject() {
if (object == NOT_INITIALIZED) {
synchronized (NOT_INITIALIZED) {
if (object == NOT_INITIALIZED) {
final Object tmpRef = createObject();
object = tmpRef;
}
}
}
return object;
}
/**
* Creates some object which initialization is not thread safe
* #return required object or NOT_INITIALIZED
* */
private Object createObject() {
//do some work here
}
}
Here final variable tmpRef is used for storing created object before assigning it to checked variable object . This works in tests but I can't say it's correct for sure and won't be optimsed by compiler.
Can this appraoch be used or object field must be declared as volatile?
Also variant with wrapper class was considered where the line
final Object tmpRef = createObject();
must be replaced with this one:
Object tmpRef = new FinalWrapper(createObject()).getVal();
Wrapper class looks like this:
private class FinalWrapper {
private final Object val;
public FinalWrapper(Object val) {
this.val = val;
}
public Object getVal() {
return val;
}
}
Can some of this examples be safely used in multithreaded environment (especially variant with final local field)?
object = NOT_INITIALIZED;
If you envision this as a trick which will avoid the problems of the usual lazy singleton where you would simply have
object = null;
then it is incorrect; your trick didn't win you any thread safety. You cannot beat the standard double-checked idiom with the volatile variable pointing to the lazily initialized object. So my suggestion would be to get rid of the extra complexity, use null, and use volatile.
Answering your comments:
It's guranteed by JMM that calss initialization with only final fields is always threadsafe.
Class initialization is always thread-safe, regardless of the kind of fields. Every usage of the class is guaranteed to see the objects referred by static fields at least as up-to-date as they were at the time that all class init code completed.
Is the same applicable for local final fields?
The object reached by dereferencing a final field will be at least as up-to-date as it was at the time the constructor of the object containing the final field completed. However, in your solution you never even dereference the field, you just check its value. It is strictly equivalent to check for equality to null as to the value of the NOT_INITIALIZED constant.
You should mark the object variable as volatile to guarantee thread safety, also note that this pattern is only safe in Java 1.5 and later.
This is a tricky piece of code, to quote Joshua Bloch:
The idiom is very fast but also complicated and delicate, so don't be
tempted to modify it in any way. Just copy and paste -- normally not a
good idea, but appropriate here

Are non-final initializers threadsafe?

It is guranteed or not that every thread sees the value of an instance initializer (the expression right to the equal sign of a field) for a non-final field? For example:
class Foo {
private boolean initialized = false; // Initializer
private final Lock lock = new ReentrantLock();
public void initialize() {
lock.lock()
try {
// Is initialized always false for the first call of initialize()?
if (initialized) {
throw new IllegalStateException("already initialized");
}
// ...
initialized = true;
} finally {
lock.unlock();
}
}
}
In that specific case you are fine because false is also the default value for boolean fields. If your instance variable initialisation were:
private boolean initialized = true;
Then you would have no guarantee that a thread would read true.
Note that if the field were static, you would have such a guarantee due to class loading semantics.
Reference: JLS 17.4.4 (emphasis mine)
The write of the default value (zero, false, or null) to each variable synchronizes-with the first action in every thread.
Although it may seem a little strange to write a default value to a variable before the object containing the variable is allocated, conceptually every object is created at the start of the program with its default initialized values.
The same stands for initialzers that is true for referencing fields:
If you want other threads to see its current value you have to use volatile.
volatile is not surefire however: most of the case you have to use synchronized or other means of synchronizing in order to be sure but in this case a volatile will be enough.
Please refer to this question about the usage of volatile and about thread safety.
Another thing is that only one thread can construct an object and the instance initialization is happening when the object is being constructed. You have to taker care however not to let the this reference escape from the constructor.
It seems to me that what you are looking for is a thread-safe way of lazy initialization. Since direct use of low-level classes such as ReentrantLock can be quite hard to do correctly, I would instead recommend the double-check idiom:
private volatile FieldType field = null; // volatile!
public FieldType getField() {
FieldType result = field; // read volatile field only once, after init
if (result == null) {
synchronized(this) {
result = field;
if (result == null) {
result = computeFieldValue();
field = result;
}
}
}
return result;
}
Note that Double-Check locking requires at least Java 1.5. On older versions of Java it was broken.
A non-final field alone is not guaranteed to be correctly seen, unless you have some other protection such as a lock or synchronized block. i.e. in this case it will always be correct due to the way the value is used.
BTW: For simplicity reasons, I suggest you always structure your code so the component is initialized in the constructor. This avoids such issues as checking the objects is not initialised or initialised twice.

Modifying a static variable in non-synchronized static method, is there a danger to thread safety?

I have a class with a static method modifying a static variable as follows, does this method needs to be synchonized for thread safe operations ?
public final class IdManager {
private static int noOfIdsInReserveCurrently = 100;
private static final AtomicInteger allotedUserIdsCount;
public static int getNewId(){
noOfIdsInReserveCurrently--;
....
return allotedUserIdsCount.incrementAndGet();
}
}
Should this method have been synchronized?
Well it's certainly not safe as it is. Two threads could both read the value, but decrement their local copy, then both write. Badness.
You could synchronize it (and all other aspects to the variable) - but it would be better to use AtomicInteger which is designed for exactly this sort of thing. That's fine if the only shared state you're modifying is that one value; if you're trying to modify more shared state atomically (e.g. some "next ID" counter as well as the number of outstanding IDs) then you would need to either thing really, really carefully about the various interleavings, or use a synchronized block instead.

Synchronized blocks in constructors

I have a class with a static var like so
private static Object sMyStaticVar;
if i want to assign a value to this var in the constructor I have code like
if(sMyStaticVar == null) sMyStaticVar = new CustomObject(someRuntimeObject);
where someRuntimeObject is an object that is not available at the time my class is loaded and therefore prevents me from declaring my static var like the below
private static Object sMyStaticVar = new CustomObject(someRuntimeObject);
my question is, is the initialization of the static var object in the constructor thread safe? My instincts tell me its not and i should synchronise using the non-runtime class type as the lock, like the below
synchronized(MyClass.class)
{
if(sMyStaticVar == null) sMyStaticVar = new CustomObject(someRuntimeObject);
}
(as opposed to the runTime type obtained from getClass())
but as my instincts are usually wrong I would be grateful if anyone could shed some light on this for me!
If it is static, you should not assign it in the constructor. Make a static initializer method that does that public static synchronized void initialize(someRuntimeObject).
Note the synchronized keyword: it is is the same as synchronizing on MyClass.class
You are right, the following is open to race conditions:
if(sMyStaticVar == null) sMyStaticVar = new CustomObject(someRuntimeObject);
Two threads could check sMyStaticVar at the same time, see null, create two objects, etc...
This means that you need synchronization. You could either synchronize on some existing object (there are multiple choices), or you could create an object just for the prurpose, so that you don't have to share the lock with anyone else, risking unnecessary contention:
private static Object sMyStaticVar;
private static Object sMyStaticVarLock = new Object();
Then, in the constructor:
synchronized(sMyStaticVarLock)
{
if(sMyStaticVar == null) sMyStaticVar = new CustomObject(someRuntimeObject);
}
This syncrhonization is needed, but it's not enough to achieve thread safety.
You also need to ensure visibility of the field's value when you access it. So, you should either declare that field as volatile or add the same synchronization to every access of that field.

Categories

Resources