I have two methods in my class, which will be executed within concurrent environment:
class Clazz {
private int counter = 0;
private volatile Map<..> map = new ConcurrentHashMap<>();
private int[] array;
public void concurrentMethod() {
...perform some actions with map...
}
public int nonConcurrentMethod() {
...reinitialize the map...change references...
counter++;
return array[counter];
}
}
The question is following: assuming that nonConcurrentMethod
is to be called by only one thread at a time, should I explicitly specify counter
and array
as a volatile
fields? Make counter atomic
?
My thoughts are it'd be better to insure that everything should work without glitches on a real production.
Usually it's the entire class which has specific thread-safe semantics e.g. HashMap
is not thread-safe while ConcurrentHashMap
is. This is especially important if you are building a library, people might go around your design by calling nonConcurrentMethod()
from multiple threads.
IMO if you can't split Clazz
into two separate classes with different thread-safe semantics it would be prudent to make nonConcurrentMethod()
thread-safe. In case nonConcurrentMetho()
is called from multiple threads the performance will degrade but the correctness will be retained, hopefully avoiding hard to find bugs.
You can try an internal lock, which hopefully will not be too costly due to biased locking optimizing it when the lock is acquired from a single thread:
private final Object lock = new Object();
public int nonConcurrentMethod() {
synchronized(lock) {
...reinitialize the map...change references...
counter++;
return array[counter];
}
}
Make sure that at least one of the Clazz
fields is final
to ensure safe publication.