I was reading about safe publication from "Java Concurrency in Practice" and needs help to understand this one example. I know it is simple but looks like i got too much into it and got confused.
public class VolatileCachedFactorizer implements Servlet {
private volatile OneValueCache cache =
new OneValueCache(null, null);
public void service(ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = cache.getFactors(i);
if (factors == null) {
factors = factor(i);
cache = new OneValueCache(i, factors);
}
encodeIntoResponse(resp, factors);
}
}
class OneValueCache {
private final BigInteger lastNumber;
private final BigInteger[] lastFactors;
public OneValueCache(BigInteger i,
BigInteger[] factors) {
lastNumber = i;
lastFactors = Arrays.copyOf(factors, factors.length);
}
public BigInteger[] getFactors(BigInteger i) {
if (lastNumber == null || !lastNumber.equals(i))
return null;
else
return Arrays.copyOf(lastFactors, lastFactors.length);
}
}
Above are the two classes, One is VolatileCachedFactorizer which is a servlet and will be initialized only once by the container and each request would call service method to get the factors of the number passed.
Now, OneValueCache is an immutable object which would cache the latest number in the cache along with its factors.
Now, as per the book it is safely published.
My question is that OneValueCache is not declared final in VolatileCachedFactorizer although all its fields are final. When the constructor of OneValueCache is executed from service method then isn't the following scenario possible -
lastNumber would be properly initialized (as it is final) but lastFactors is not as both these statements are atomic. So, are there chances that it might be in an improper state.
If OneValueCache was declared final in VolatileCachedFactorizer then JVM would guarantee that it would be properly initialized.
Thanks
The short answer to your specific question is no. But the thing to note is that the OneValueCache instance "cache" is created in the service method and immediately made visible to all other threads since that is made possible due to the characteristics of the volatile keyword. If thread A writes to a volatile variable then once it is finished then thread B would see all the changes that thread A made if it encounters the volatile variable.
With volatile there are no reordering of memory operations and once the object is created then it is immediately available to be read since the volatile variables are not cached within a local cache wherein it is not visible to other threads on another processor.
If your confusion is on the cache object being properly instantiated then yes, then only the properly constructed immutable cache object be made visible to other threads.
Related
I'm reading "Java concurrency in practice" and one thing is confusing me.
class OneValueCache {
private final BigInteger lastNumber;
private final BigInteger[] lastFactors;
public OneValueCache(BigInteger lastNumber, BigInteger[] lastFactors) {
this.lastNumber = lastNumber;
this.lastFactors = Arrays.copyOf(lastFactors, lastFactors.length);
}
public BigInteger[] getFactors(BigInteger i) {
if (lastNumber == null || !lastNumber.equals(i)) {
return null;
}
return Arrays.copyOf(lastFactors, lastFactors.length);
}
}
class VolatileCachedFactorized implements Servlet {
private volatile OneValueCache cache = new OneValueCache(null, null);
public void service(ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = cache.getFactors(i);
if (factors == null) {
factors = factor(i);
cache = new OneValueCache(i, factors);
}
encodeIntoResponse(resp, factors);
}
}
In above code author uses volatile with reference to immutable OneValueCache, but a few page later he writes:
Immutable objects can be used safely by any thread without additional synchronization, even when synchronization is not used to publish them.
So .. volatile is not necessary in above code?
There are kind of 2 level of "thread-safety" that is being applied here. One is at reference level ( done using volatile). Think of an example where a thread reads the value to be null vs other thread seeing some reference value ( changed in between). Volatile will guarantee the publication of one thread is visible to another. But aAnother level of thread safety will be required to safeguard the internal members themselves which have the potential to be changed. Just having a volatile will have no impact on the data within the Cache ( like lastNumber, lastFactors). So immutability will help in that case.
As a general rule ( referred here) as a good thread safe programming practice
Do not assume that declaring a reference volatile guarantees safe
publication of the members of the referenced object
This is the same reason why putting a volatile keyword in front of a HasMap variable does not make it threadsafe.
cache is not a cache, it is a reference to a cache. The reference needs to be volatile in order that the switch of cache is visible to all threads.
Even after assignment to cache, other threads may be using the old cache, which they can safely do. But if you want the new cache to be seen as soon as it is switched, volatile is needed. There is still a window where threads might be using the old cache, but volatile guarantees that subsequent accessors will see the new cache. Do not confuse 'safety' with 'timeliness'.
Another way to look at this is to note that immutability is a property of the cache object, and cannot affect the use of any reference to that object. (And obviously the reference is not immutable, since we assign to it).
public class VolatileCachedFactorizer extends GenericServlet implements Servlet {
private volatile OneValueCache cache = new OneValueCache(null, null);
public void service(ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = cache.getFactors(i);
if (factors == null) {
factors = factor(i); //----------> thread A
cache = new OneValueCache(i, factors); //---------> thread B
}
encodeIntoResponse(resp, factors);
}
}
public class OneValueCache {
private final BigInteger lastNum;
private final BigInteger[] lastFactors;
public OneValueCache(BigInteger i, BigInteger[] lastFactors){
this.lastNum = i;
this.lastFactors = lastFactors;
}
public BigInteger[] getFactors(BigInteger i){
if(lastNum == null || !lastNum.equals(i))
return null;
else
return Arrays.copyOf(lastFactors, lastFactors.length);
}
}
This is the code from the book Java concurrency in practice, my question is in this code specifically, we can remove the final keyword from the OneValueCache and still preserve the thread-safe, right, I am not sure why are these final keyword necessary.
Thanks.
It is not necessary in this very situation, but it is a bit complicated to reason about when done without the "final" keywords.
Basically there are two concurrency problems we are trying to solve:
1) The visibility of the "cache" reference - solved by using "volatile" here.
2) State consistency (safe publication) of the OneValueCache object. As stated in the "Java Concurrency In Practice" book:
The publication requirements for an object depend on its mutability:
Immutable objects can be published through any mechanism;
Effectively immutable objects must be safely published;
...
So if you remove "final" usages from OneValueCache then you are making this class more of an effectively immutable class, at least from the visibility standpoint, because "final" has memory visibility semantics (somewhat similar to "volatile") under concurrency.
So now instead of forgetting about object state consistency for any usages of the class you are forcing yourself to always think about safe publication when using it.
It also resembles what is described in chapter "16.1.4 Piggybacking on synchronization", because you would use the happens-before of writing/reading the volatile reference to guarantee that the OneValueCache object is in consistent state to all the threads after the construction. Basically it seems to be just a different explanation of the "safe publication" problem in this context.
If we have 2 classes that operate on the same object under different threads and we want to avoid race conditions, we'll have to use synchronized blocks with the same monitor like in the example below:
class A {
private DataObject mData; // will be used as monitor
// thread 3
public setObject(DataObject object) {
mData = object;
}
// thread 1
void operateOnData() {
synchronized(mData) {
mData.doSomething();
.....
mData.doSomethingElse();
}
}
}
class B {
private DataObject mData; // will be used as monitor
// thread 3
public setObject(DataObject object) {
mData = object;
}
// thread 2
void processData() {
synchronized(mData) {
mData.foo();
....
mData.bar();
}
}
}
The object we'll operate on, will be set by calling setObject() and it will not change afterwards. We'll use the object as a monitor. However, intelliJ will warn about synchronization on a non-final field.
In this particular scenario, is the non-local field an acceptable solution?
Another problem with the above approach is that it is not guaranteed that the monitor (mData) will be observed by thread 1 or thread 2 after it is set by thread 3, because a "happens-before" relationship hasn't been established between setting and reading the monitor. It could be still observed as null by thread 1 for example. Is my speculation correct?
Regarding possible solutions, making the DataObject thread-safe is not an option. Setting the monitor in the constructor of the classes and declaring it final can work.
EDIT Semantically, the mutual exclusion needed is related to the DataObject. This is the reason that I don't want to have a secondary monitor. One solution would be to add lock() and unlock() methods on DataObject that need to be called before working on it. Internally they would use a Lock Object. So, the operateOnData() method becomes:
void operateOnData() {
mData.lock()
mData.doSomething();
.....
mData.doSomethingElse();
mData.unlock();
}
You may create a wrapper
class Wrapper
{
DataObject mData;
synchronized public setObject(DataObject mData)
{
if(this.mData!=null) throw ..."already set"
this.mData = mData;
}
synchronized public void doSomething()
{
if(mData==null) throw ..."not set"
mData.doSomething();
}
A wrapper object is created and passed to A and B
class A
{
private Wrapper wrapper; // set by constructor
// thread 1
operateOnData()
{
wrapper.doSomething();
}
Thread 3 also has a reference to the wrapper; it calls setObject() when it's available.
Some platforms provide explicit memory-barrier primitives which will ensure that if one thread writes to a field and then does a write barrier, any thread which has never examined the object in question can be guaranteed to see the effect of that write. Unfortunately, as of the last time I asked such a question, Cheapest way of establishing happens-before with non-final field, the only time Java could offer any guarantees of threading semantics without requiring any special action on behalf of a reading thread was by using final fields. Java guarantees that any references made to an object through a final field will see any stores which were performed to final or non-fields of that object before the reference was stored in the final field but that relationship is not transitive. Thus, given
class c1 { public final c2 f;
public c1(c2 ff) { f=ff; }
}
class c2 { public int[] arr; }
class c3 { public static c1 r; public static c2 f; }
If the only thing that ever writes to c3 is a thread which performs the code:
c2 cc = new c2();
cc.arr = new int[1];
cc.arr[0] = 1234;
c3.r = new c1(cc);
c3.f = c3.r.f;
a second thread performs:
int i1=-1;
if (c3.r != null) i1=c3.r.f.arr[0];
and a third thread performs:
int i2=-1;
if (c3.f != null) i2=c3.f.arr[0];
The Java standard guarantees that the second thread will, if the if condition yields true, set i1 to 1234. The third thread, however, might possibly see a non-null value for c3.f and yet see a null value for c3.arr or see zero in c3.f.arr[0]. Even though the value stored into c3.f had been read from c3.r.f and anything that reads the final reference c3.r.f is required to see any changes made to that object identified thereby before the reference c3.r.f was written, nothing in the Java Standard would forbid the JIT from rearranging the first thread's code as:
c2 cc = new c2();
c3.f = cc;
cc.arr = new int[1];
cc.arr[0] = 1234;
c3.r = new c1(cc);
Such a rewrite wouldn't affect the second thread, but could wreak havoc with the third.
A simple solution is to just define a public static final object to use as the lock. Declare it like this:
/**Used to sync access to the {#link #mData} field*/
public static final Object mDataLock = new Object();
Then in the program synchronize on mDataLock instead of mData.
This is very useful, because in the future someone may change mData such that it's value does change then your code would have a slew of weird threading bugs.
This method of synchronization removes that possibility. It also is really low cost.
Also having the lock be static means that all instances of the class share a single lock. In this case, that seems like what you want.
Note that if you have many instances of these classes, this could become a bottleneck. Since all of the instances are now sharing a lock, only a single instance can change any mData at a single time. All other instances have to wait.
In general, I think something like a wrapper for the data you want to synchronize is a better approach, but I think this will work.
This is especially true if you have multiple concurrent instances of these classes.
The class below is meant to be immutable (but see edit):
public final class Position extends Data {
double latitude;
double longitude;
String provider;
private Position() {}
private static enum LocationFields implements
Fields<Location, Position, List<Byte>> {
LAT {
#Override
public List<byte[]> getData(Location loc, final Position out) {
final double lat = loc.getLatitude();
out.latitude = lat;
// return an arrayList
}
#Override
public void parse(List<Byte> list, final Position pos)
throws ParserException {
try {
pos.latitude = listToDouble(list);
} catch (NumberFormatException e) {
throw new ParserException("Malformed file", e);
}
}
}/* , LONG, PROVIDER, TIME (field from Data superclass)*/;
}
// ========================================================================
// Static API (factories essentially)
// ========================================================================
public static Position saveData(Context ctx, Location data)
throws IOException {
final Position out = new Position();
final List<byte[]> listByteArrays = new ArrayList<byte[]>();
for (LocationFields bs : LocationFields.values()) {
listByteArrays.add(bs.getData(data, out).get(0));
}
Persist.saveData(ctx, FILE_PREFIX, listByteArrays);
return out;
}
public static List<Position> parse(File f) throws IOException,
ParserException {
List<EnumMap<LocationFields, List<Byte>>> entries;
// populate entries from f
final List<Position> data = new ArrayList<Position>();
for (EnumMap<LocationFields, List<Byte>> enumMap : entries) {
Position p = new Position();
for (LocationFields field : enumMap.keySet()) {
field.parse(enumMap.get(field), p);
}
data.add(p);
}
return data;
}
/**
* Constructs a Position instance from the given string. Complete copy
* paste just to get the picture
*/
public static Position fromString(String s) {
if (s == null || s.trim().equals("")) return null;
final Position p = new Position();
String[] split = s.split(N);
p.time = Long.valueOf(split[0]);
int i = 0;
p.longitude = Double.valueOf(split[++i].split(IS)[1].trim());
p.latitude = Double.valueOf(split[++i].split(IS)[1].trim());
p.provider = split[++i].split(IS)[1].trim();
return p;
}
}
Being immutable it is also thread safe and all that. As you see the only way to construct instances of this class - except reflection which is another question really - is by using the static factories provided.
Questions :
Is there any case an object of this class might be unsafely published ?
Is there a case the objects as returned are thread unsafe ?
EDIT : please do not comment on the fields not being private - I realize this is not an immutable class by the dictionary, but the package is under my control and I won't ever change the value of a field manually (after construction ofc). No mutators are provided.
The fields not being final on the other hand is the gist of the question. Of course I realize that if they were final the class would be truly immutable and thread safe (at least after Java5). I would appreciate providing an example of bad use in this case though.
Finally - I do not mean to say that the factories being static has anything to do with thread safety as some of the comments seem(ed) to imply. What is important is that the only way to create instances of this class is through those (static of course) factories.
Yes, instances of this class can be published unsafely. This class is not immutable, so if the instantiating thread makes an instance available to other threads without a memory barrier, those threads may see the instance in a partially constructed or otherwise inconsistent state.
The term you are looking for is effectively immutable: the instance fields could be modified after initialization, but in fact they are not.
Such objects can be used safely by multiple threads, but it all depends on how other threads get access to the instance (i.e., how they are published). If you put these objects on a concurrent queue to be consumed by another thread—no problem. If you assign them to a field visible to another thread in a synchronized block, and notify() a wait()-ing thread which reads them—no problem. If you create all the instances in one thread which then starts new threads that use them—no problem!
But if you just assign them to a non-volatile field and sometime "later" another thread happens to read that field, that's a problem! Both the writing thread and the reading thread need synchronization points so that the write truly can be said to have happened before the read.
Your code doesn't do any publication, so I can't say if you are doing it safely. You could ask the same question about this object:
class Option {
private boolean value;
Option(boolean value) { this.value = value; }
boolean get() { return value; }
}
If you are doing something "extra" in your code that you think would make a difference to the safe publication of your objects, please point it out.
Position is not immutable, the fields have package visibility and are not final, see definition of immutable classes here: http://www.javapractices.com/topic/TopicAction.do?Id=29.
Furthermore Position is not safely published because the fields are not final and there is no other mechanism in place to ensure safe publication. The concept of safe publication is explained in many places, but this one seems particularly relevant: http://www.ibm.com/developerworks/java/library/j-jtp0618/
There are also relevant sources on SO.
In a nutshell, safe publication is about what happens when you give the reference of your constructed instance to another thread, will that thread see the fields values as intended? the answer here is no, because the Java compiler and JIT compiler are free to re-order the field initialization with the reference publication, leading to half baked state becoming visible to other threads.
This last point is crucial, from the OP comment to one of the answers below he appears to believe static methods somehow work differently from other methods, that is not the case. A static method can get inlined much like any other method, and the same is true for constructors (the exception being final fields in constructors post Java 1.5). To be clear, while the JMM doesn't guarantee the construction is safe, it may well work fine on certain or even all JVMs. For ample discussion, examples and industry expert opinions see this discussion on the concurrency-interest mailing list: http://jsr166-concurrency.10961.n7.nabble.com/Volatile-stores-in-constructors-disallowed-to-see-the-default-value-td10275.html
The bottom line is, it may work, but it is not safe publishing according to JMM. If you can't prove it is safe, it isn't.
The fields of the Position class are not final, so I believe that their values are not safely published by the constructor. The constructor is therefore not thread-safe, so no code (such as your factory methods) that use them produce thread-safe objects.
I have a code like the one below where an object is shared among two threads (the main thread and the Monitor thread). Do I have to declare MyObject globally and make it volatile to ensure it will be pushed to memory? Otherwise the if statement can print "Not null" if MyObject is only locally accessed by the thread and is not declared volatile, right?
public static void main(String[] args) {
MyObject obj = MyObjectFactory.createObject();
new Monitor(obj).start();
Thread.sleep(500);
if(obj == null)
System.out.println("Null");
else
System.out.println("Not null");
}
public void doSomethingWithObject(MyObject obj) {
obj = null;
}
private class Monitor extends Thread {
public Monitor(MyObject obj) {
this.obj=obj;
}
public void run() {
doSomethingWithObject(obj);
}
}
Note: The code example may not compile since I wrote it myself here on Stackoverflow. Consider it as a mix of pseudo code and real code.
The instance is shared but the references to it are not. Example:
String a = "hello";
String b = a;
b = null; // doesn't affect a
a and b are references to the same instance; changing one reference has no effect on the instance or any other references to the same instance.
So if you want to share state between threads, you will have to create a field inside MyObject which has to be volatile:
class MyObject { public volatile int shared; }
public void doSomethingWithObject(MyObject obj) {
obj.shared = 1; // main() can see this
}
Note that volatile just works for some types (references and all primitives except long). Since this is easy to get wrong, you should have a look at types in java.util.concurrent.atomic.
[EDIT] What I said above isn't correct. Instead, using volatile with long works as expected for Java 5 and better. This is the only way to ensure atomic read/writes for this type. See this question for references: Is there any point in using a volatile long?
Kudos go to Affe for pointing that out. Thanks.
You would rather have to synchronize on the object to ensure it will be set to null before the if check. Setting it to volatile only means changes will be "seen" immediately by other threads, but it is very likely that the if check will be executed before the doSomethingWithObject call.
If you want your object to go through a read-update-write scheme atomically, volatile won't cut it. You have to use synchronisation.
Volatility will ensure that the variable will not be cached in the current thread but it will not protect the variable from simultaneous updates, with the potential for the variable becoming something unexpected.
IBM's developerWorks has a useful article on the subject.
Your example consists only one thread, Monitor, which is created and run in main().
"make it volatile to ensure it will be pushed to memory?" - on the contrary, when you declare a variable as volatile - it ensures that it's NOT being "pushed" (cached) to the thread-local memory, cause there might be other threads that will change the value of the variable.
In order to make sure you print the correct value of a variable you should synchronize the method doSomethingWithObject (change the signature of the method to):
public synchronized void doSomethingWithObject(MyObject obj)
or create synchronized blocks around:
obj = null;
and
this.obj=obj;