Will calling a setter after constructor execution but before returning the reference will be a safe publication ?
public class SafePublication {
private int i = 0;
private SafePublication() {
i = 10;
}
// Here we are calling setter are object creation.
//Will this change be visible to other threads
public static SafePublication getInstance() {
SafePublication pub = new SafePublication();
pub.setVal(20);
return pub;
}
private void setVal(int x) {
this.i = x;
}
}
No it won't be safe.
The setVal method is not synchronized, and i is not volatile. Therefore, there will be no synchronization point between an update to i (via setVal) and any code run on another thread that reads i. The fact that the setVal call happens in the thread that constructs the instance makes on difference.
The bottom line is that another thread may see the value of i as any one of 0, 10 or 20.
How may another thread see that value if the reference to the object has not been returned yet?
It is not. The problem is that the other thread may not see the correct value of i.
I think you are confusing this situation with the case where the field is final. There, the JLS does specify that the field is safely published. The problem is that this guarantee does not apply to non-final fields; see JLS 17.5. The wording is as follows:
"An object is considered to be completely initialized when its constructor finishes. A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields. "
(Emphasis added)
i would rather say another thread may see the value of i as any one of 10 or 20. It is guaranteed not to see 0.
AFAIK, there is nothing in JLS 17.4 or JLS 17.5 that offers that guarantee. The only thing that is guaranteed is that nothing will see the value of i before default initialization has taken place. (Please feel free to prove me wrong ... with references to the JLS.)
Related
From the book Java Concurrency In Practice:
To publish an object safely, both the reference to the object and the object’s state must be made visible to other threads at the same time. A properly constructed object can be safely published by:
Initializing an object reference from a static initializer;
Storing a reference to it into a volatile field or AtomicReference;
Storing a reference to it into a final field of a properly constructed object; or
Storing a reference to it into a field that is properly guarded by a lock.
My question is:
Why does the bullet point 3 have the constrain:"of a properly constructed object", but the bullet point 2 does not have?
Does the following code safely publish the map instance? I think the code meets the conditions of bullet point 2.
public class SafePublish {
volatile DummyMap map = new DummyMap();
SafePublish() throws InterruptedException {
new Thread(new Runnable() {
#Override
public void run() {
// Safe to use 'map'?
System.out.println(SafePublish.this.map);
}
}).start();
Thread.sleep(5000);
}
public static void main(String[] args) throws InterruptedException {
SafePublish safePublishInstance = new SafePublish();
}
public class DummyMap {
DummyMap() {
System.out.println("DummyClass constructing");
}
}
}
The following debug snapshot pic shows the map instance is null at the time of the execution is entering the construction of SafePublish. What happens if another thread now trying to read the map reference? Is it safe to read?
It's because final fields are guaranteed to be visible to other threads only after the object construction while the visibility of writes to volatile fields are guaranteed without any additional conditions.
From jls-17, on final fields:
An object is considered to be completely initialized when its constructor finishes. A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields.
on volatile fields:
A write to a volatile variable v (§8.3.1.4) synchronizes-with all subsequent reads of v by any thread (where "subsequent" is defined according to the synchronization order).
Now, regarding your specific code example, JLS 12.5 guarantees that field initialization occurs before the code in your constructor is executed (see steps 4 and 5 in JLS 12.5, which is a bit too long to quote here). Therefore, Program Order guarantees that the constructor's code will see map initialized, regardless of whether it's volatile or final or just a regular field. And since there's a Happens-Before relation before field writes and the start of a thread, even the thread you're creating in the constructor will see map as initialized.
Note that I specifically wrote "before code in your constructor is executed" and not "before the constructor is executed" because that's not the guarantee JSL 12.5 makes (read it!). That's why you're seeing null in the debugger before the first line of the constructor's code, yet the code in your constructor is guaranteed to see that field initialized.
Please consider following code snippet.
public class Visibility {
private volatile SomeData data;
public static class SomeData {
private int number;
public SomeData(int number) {
this.number = number;
}
public int getNumber() {
return number;
}
}
public void initialize() {
data = new SomeData(42);
}
public SomeData getData() {
return data;
}
}
If number field was final, any thread that sees data reference is not null (after other thread called initialize) is also guaranteed to see number field value as 42.
Do we have the same guarantees for non final field?
In other words, is it possible for some thread to observe non-null
data reference, but number field as 0?
Thanks in advance!
It is not possible for some thread to observe non-null data reference, but number field as 0.
See the doc of volatile:
This means that changes to a volatile variable are always visible to
other threads. What's more, it also means that when a thread reads a
volatile variable, it sees not just the latest change to the volatile,
but also the side effects of the code that led up the change.
So when you get a non-null data, it must have been successfully initiated, the number must be non-zero.
In general, yes, it is possible to see a field in a partially constructed state if the field is not published in a safe manner. In the particular case of your question, the volatile keyword is a satisfactory form of safe publication. According to Java Concurrency in Practice:
To publish an object safely, both the reference to the object and the
object's state must be made visible to other threads at the same time.
A properly constructed object can be safely published by:
Initializing an object reference from a static initializer.
Storing a reference to it into a volatile field.
Storing a reference to it into a final field.
Storing a reference to it into a field that is properly guarded by a (synchronized) lock.
For more information, see the following:
Does a volatile reference really guarantee that the inner state of the object is visible to other threads?
Java multi-threading & Safe Publication
Java Concurrency in Practice
Discussing this answer I was wondered why didn't we use sychronization when assigning default values.
class StateHolder {
private int counter = 100;
private boolean isActive = false;
public synchronized void resetCounter() {
counter = 0;
isActive = true;
}
public synchronized void printStateWithLock() {
System.out.println("Counter : " + counter);
System.out.println("IsActive : " + isActive);
}
public void printStateWithNoLock() {
System.out.println("Counter : " + counter);
System.out.println("IsActive : " + isActive);
}
}
This class looks thread safe because access to its fields is managed by a synchronized method. That way, all we have to do is to publish it safely. For instance:
public final StateHolder stateHolder = new StateHolder();
Can it be considered as a safe publication? I think no, it cannot. Consulting the final field semantic (emphasized mine) I figured out that the only thing guarnteeed is that stateHolder reference is not a stale one. :
A thread that can only see a reference to an object after that object
has been completely initialized is guaranteed to see the correctly
initialized values for that object's final fields.
final field semantic is not concerned about the state of the ojbect referenced to by the final field. That way, another thread might as well see default values of the fields.
QUESTION: How can we guarantee memory consistency of the filed's values assigned within a constructor or instance initializer?
I think we have to declare them either volatile or final as that there is no happens-before relationship bethween assigning a reference and constructor invocation. But lots of library classes does not declare fields that way. java.lang.String is an example:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence{
//...
private int hash; //neither final nor volatile
//...
}
final can guarantee you that you'll see the assigned value to an instance variable after the instance construction without the need of any further action. You just need to make sure that you don't leak the constructed instance within the constructor.
volatile can also guarantee you that you'll see the default value that you set for some instance variable, because the instance variable initializers are guaranteed to be executed before the end of the constructor per JLS 12.5 Creation of New Class Instances.
Safe publication is not entirely trivial, but if you stick with one of the popular mechanisms for achieving it, you should be perfectly fine. You can take a look at Safe Publication and Safe Initialization in Java for some more interesting details.
As for String.hash, it's a popular example of the so-called benign data races. The accesses to the hash instance variable allow both racing of a read and write and racing of two writes. To illustrate just the latter, two threads can simultaneously:
see the initial value of 0
decide that they are the first to calculate the hash
calculate the hash code and write to the same variable without any synchronization
The race was still allowed and considered to be benign because of two reasons:
Hash code calculation for the immutable String instances is an idempotent operation.
Writes of 32-bit values are guaranteed not to tear.
Even benign data races are still not recommended though. See Benign data races: what could possibly go wrong? or Nondeterminism is unavoidable, but data races are pure evil.
I am recently reading the book "Java Concurrency in Practice". One example of "safe publish" it gives is to initialize a private int field n during construction, and a later assertion on that field n == "expect value" through a public method could still be failed if it is called from another thread. This makes me feel worried in that, assuming all private fields are initialized only once, do we still have to mark them as volatile or wrap them into ThreadLocal or even use an AtomicReference to get a pure thread safe java class, since these private fields, though not visible outside, definitely could be referenced by the method(s) called by other threads.
EDIT: Just to be clear - the assertion is failed because the calling thread sees a stale value of n, even though it has been set during construction. This is a clearly a memory-visibility issue. Problem is whether synchronizing on n is worthy of the overhead after all, since it is only initialized once, and as a private field, author can make sure it won't be changed again.
This specific case is properly documented in the JSR 133: Java Memory Model and Thread
Specification. It even has a dedicated code sample page 14 section 3.5 Final Fields that exactly match your question.
To summarize:
A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object’s final fields.
There is no guarantee for non final fields
It means that you have to make sure that an happens-before occurs between your object creation in a thread and its usage in another thread. You can use synchronized, volatile or any other mean to enforce an happens-before.
Since you say in another comment that the field is only set during construction, I would make it... final. Also, such shared objects between threads could suggest some design smell; I would review my design to make sure that I am not creating an overly complex, tightly coupled, hard to debug system.
If the fields are never used outside the class, wrapping their usages with synchronized blocks or inside synchronized functions, two threads won't concurrently modify these fields.
volatile keyword is just a part of thread safety. It only makes the value of a field never be cached, always read from memory. Take this example.
private int myPrivateField = 0;
void someFunction() {
while(myPrivateField ==0) {
}
}
void otherFunction() {
myPrivateField = 1;
}
If someFunction() is called from one thread and it's running for a while,
when you call otherFunction() the value of myPrivateField will not be
"updated" inside someFunction, it was cached to 0 as an otimization.
Making myPrivateField as volatile, the value will always be the one
in memory.
For the example, there won't be much difference for the functions be
synchronized, but without synchronization, you can read a value in an
inconsistent state.
Only final fields are guaranteed to be visible after constructor. Any other field requires some visibility mechanism, such as synchronized or volatile.
This is not as much of a burden as it seems: if the field is not final, then it can be changed by another thread while you're reading it. If teh field can be changed, then the last assigned value must be propagated from the writer thread to the reader thread, whether the writer thread called the constructor or a setter.
If the change in this field is not related to any other field in the class, then the field should be volatile. If the field is related to other fields in the class, then use synchronized or other, more modern locking primitives.
Not answering the entire question, but it should be pointed out that using ThreadLocal is exactly the wrong thing to use if you want to ensure visibility of updated values in all threads. Consider the following code:
class Test {
private static final ThreadLocal<Integer> value = new ThreadLocal<>();
public static void main(String[] args) throws InterruptedException {
System.out.println("From main Thread, value is " + value.get());
value.set(42);
System.out.println("Value has been changed");
Thread t = new Thread() {
public void run() {
System.out.println("From other Thread, value is " + value.get());
}
};
t.start();
t.join();
System.out.println("From main Thread, value is " + value.get());
}
}
This will output the following:
From main Thread, value is null
Value has been changed
From other Thread, value is null
From main Thread, value is 42
i.e. the other thread doesn't see the updated value. This is because changes to the value of a ThreadLocal is, by definition, localized to the thread which changes it.
My personal preference would be to use AtomicReference, since this avoids the risk of forgetting to synchronize externally; it also allows things like atomic compare-and-set, which you don't get with a volatile variable. However, this may not be a requirement for your particular application.
Assuming this class:
public class AmIThreadSafe {
private int a;
private int b;
AmIThreadSafe(int a, int b) {
this.a = a;
this.b = b;
}
}
Assuming that instance's reference to this class (declared as volatile) is accessible by some threads (leading to race condition) as soon as the this(reference) escapes:
volatile AmIThreadSafe instance = new AmIThreadSafe(1,2);
Here, I'm sure that the fact of assigning instance reference happens-before reading by threads.
But what about the AmIThreadSafe's fields?
Does the external volatile keyword also imply an happens-before relation concerning a and b fields?
Or is it rather possible to end up with any thread seeing stale values (default values 0 in this case since int) due to a potential statements reordering during constructor?
In other word, should I declare a and b final or volatile to prevent any surprises with the JMM or is just indicating volatile on the instance's reference enough?
----------------UPDATED POST - A GOOD ANSWER:----------------------------
The following article confirms by its sample that in my case, a and b are protected from JMM optimisations that prevent a permanent happens-before relation.
http://jeremymanson.blogspot.fr/2008/11/what-volatile-means-in-java.html
Declaring instance as volatile does not make its fields volatile, but if I understand your question correctly, then — yes, it's enough in your case.
Per §17.4.5 of the spec:
a volatile write in one thread happens-before any subsequent volatile read in another thread.
statements within the same thread have the happens-before relationship that you'd expect.
happens-before relationships are transitive.
So, if a thread perceives instance as having been initialized, then the initialization of instance happened-before it, and the initialization of instance's fields happened-before that, so the thread will perceive instance's fields as having been initialized.
No it's not enough to make it volatile. Thread safety depends on the usage though. E.g., this could still produce unexpected results if another thread is modifying the values.
assuming public variables for simplicity
volatile AmIThreadSafe instance = new AmIThreadSafe(1,2);
if (instance.x == 0) {
// instance.x might have changed between checking and assigning
instance.x = instance.x + 1;
}
volatile only applies to a variable (e.g., x and y are not automatically volatile just because instance is). This should be clear from JLS 8.3.1.4
The volatile in your case applies only to the reference of AmlThreadSafe. You still have to make the instance variables (a and b) volatile or access them in a synchronized block. Otherwise you can get stale data.
Yes.
thread 1 thread 2
1 write(a)
2 write(instance)
3 read(instance)
4 read(a)
Since instance is volatile, [2] happens-before [3].
Since happens-before is transitive, we have hb(1,2), hb(2,3), hb(3,4), therefore hb(1,4)
If a and b are only modified in the constructor, then in this case you should be fine because the object is created (and a and b set) BEFORE the reference is assigned to instance, and any other threads won't have locally-cached copies of the memory at those locations because it's a new object that the thread couldn't have seen before. In other words, I don't believe it's possible that another thread will ever be able to see the "default" value of 0 for a and b because the constructor will run completely before the object's reference is assigned to instance.
However if a and b can be modified after the constructor, then the other answers here are correct - you need synchronization around them.
If you are going to assume that a and b won't be modified outside of the constructor, then there's no reason not to make them final anyway, just to be safe.
Example :
class Something{
private volatile static Something instance = null;
private int x;
private int y;
private Something(){
this.x = 1;
this.y = 2;
}
public static Something getInstance() {
if (instance == null) {
synchronized (Something.class) {
if (instance == null)
instance = new Something();
}
}
}
return instance;
}
}
Explanation :
Lets say we have the above Code:
Now lets assume instance is not volatile for some time:
Thread#1 :
Comes in invoke getInstance method, Check for instance value{since null}, will go inside the IF condition, Access the Lock now again finds that instance == null, calls Something constructor. Now goes inside Constructor body.
As soon as Thread#1 goes inside Constructor body, Context Switch happens and now Thread #2 gets the turn to execute.
Thread#2 :
Invokes get Instance, But suddenly finds that instance is not null?Why{Reason will discuss just after this}and hence assign partially constructed Object to reference and returns it.
Now Situation is like this : Thread#1 Still needs to construct the Object Completely{needs to completely construct it} and Thread#2 got reference for partially constructed Object, and if it uses it like say reference.x //will print "x" Default Value and not "1"
Why partially constructed Object reference is returned in case Of Thread#2 ?
Reason is simple: Statements Reordering.
The Steps are simple for Object creation and reference association :
Allocate Memory in Heap.
Execute the Body of Constructor which will initialize class members.
Once above Step is completed, Reference to newly created Object.
But Sometimes Compiler can execute these Instructions out Of order, which means :
It might happen something like this :
Allocate Memory in Heap.
Reference to newly created Object.
Execute the Body of Constructor which will initialize class members.
Once the above two Steps happens and if Context Switching Happens, then reference will point to Object which is not initialized or it might be the case that Inside Constructor Body Context Switch happens then in that case reference will refer to partially initialized Object.
If such scenario occurs then reference will neither be null nor complete and hence it will break our Singleton motivation.
Now How Volatile will save our Life from such embarrassments :
As we know Volatile work with two principles : 1)Visibility 2)Happens Before Relationship.
Now Happens Before Relationship comes into Picture here.
So reference is volatile Write, so all statements should happen before any Volatile write.Again If we look at our Object construction steps:
Allocate memory for Object
Initialize member variables{Constructor Body}
Assign Object reference to volatile variable instance.
Step 3 has Volatile Variable write and as per Happens before .. All statements write guaranteed to be made available to step 3. And since it is volatile therefore No reordering will happen between volatile and non volatile statements, which was not the case in Old Java Memory Model.
So before executing Step 3, Step 1 and Step 2 are guaranteed to be happened and made available to Step 3. {In which order Step 1 and step 2 occurs we don't bother about it.}
So from this Thread will see either Completely created Object or null