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
Related
public class Test{
private MyObj myobj = new MyObj(); //it is not volatile
public class Updater extends Thred{
myobje = getNewObjFromDb() ; //not am setting new object
}
public MyObj getData(){
//getting stale date is fine for
return myobj;
}
}
Updated regularly updates myobj
Other classes fetch data using getData
IS this code thread safe without using volatile keyword?
I think yes. Can someone confirm?
No, this is not thread safe. (What makes you think it is?)
If you are updating a variable in one thread and reading it from another, you must establish a happens-before relationship between the write and the subsequent read.
In short, this basically means making both the read and write synchronized (on the same monitor), or making the reference volatile.
Without that, there are no guarantees that the reading thread will see the update - and it wouldn't even be as simple as "well, it would either see the old value or the new value". Your reader threads could see some very odd behaviour with the data corruption that would ensue. Look at how lack of synchronization can cause infinite loops, for example (the comments to that article, especially Brian Goetz', are well worth reading):
The moral of the story: whenever mutable data is shared across threads, if you don’t use synchronization properly (which means using a common lock to guard every access to the shared variables, read or write), your program is broken, and broken in ways you probably can’t even enumerate.
No, it isn't.
Without volatile, calling getData() from a different thread may return a stale cached value.
volatile forces assignments from one thread to be visible on all other threads immediately.
Note that if the object itself is not immutable, you are likely to have other problems.
You may get a stale reference. You may not get an invalid reference.
The reference you get is the value of the reference to an object that the variable points to or pointed to or will point to.
Note that there are no guarantees how much stale the reference may be, but it's still a reference to some object and that object still exists. In other words, writing a reference is atomic (nothing can happen during the write) but not synchronized (it is subject to instruction reordering, thread-local cache et al.).
If you declare the reference as volatile, you create a synchronization point around the variable. Simply speaking, that means that all cache of the accessing thread is flushed (writes are written and reads are forgotten).
The only types that don't get atomic reads/writes are long and double because they are larger than 32-bits on 32-bit machines.
If MyObj is immutable (all fields are final), you don't need volatile.
The big problem with this sort of code is the lazy initialization. Without volatile or synchronized keywords, you could assign a new value to myobj that had not been fully initialized. The Java memory model allows for part of an object construction to be executed after the object constructor has returned. This re-ordering of memory operations is why the memory-barrier is so critical in multi-threaded situations.
Without a memory-barrier limitation, there is no happens-before guarantee so you do not know if the MyObj has been fully constructed. This means that another thread could be using a partially initialized object with unexpected results.
Here are some more details around constructor synchronization:
Constructor synchronization in Java
Volatile would work for boolean variables but not for references. Myobj seems to perform like a cached object it could work with an AtomicReference. Since your code extracts the value from the DB I'll let the code stay as is and add the AtomicReference to it.
import java.util.concurrent.atomic.AtomicReference;
public class AtomicReferenceTest {
private AtomicReference<MyObj> myobj = new AtomicReference<MyObj>();
public class Updater extends Thread {
public void run() {
MyObj newMyobj = getNewObjFromDb();
updateMyObj(newMyobj);
}
public void updateMyObj(MyObj newMyobj) {
myobj.compareAndSet(myobj.get(), newMyobj);
}
}
public MyObj getData() {
return myobj.get();
}
}
class MyObj {
}
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.
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.
Basically the following works but since I read about the final keyword I am not sure anymore if I have to declare name final if different threads access it?
Thanks in advance.
public class Test4 {
// to ensure thread-safety do we have to declare the variable name final ?
private String name;
public Test4 (String name) {
this.name = name;
}
public void start() {
new MyThread().start();
}
private class MyThread extends Thread {
public void run() {
System.out.println(name);
}
}
public static void main(String[] args) {
Test4 t = new Test4("Don't know if I am threadsafe");
t.start();
}
}
The final modifier - while preventing the member from being re-assigned - does not affect the correctness of the given code1
From the the 17.4.4 Synchronization Order section for the Java 5 Language Specification:
A synchronization order is a total order over all of the synchronization actions of an execution .. Synchronization actions induce the synchronized-with relation on actions, defined as follows:
..
An action that starts a thread synchronizes-with the first action in the thread it starts.
..
Then, since the thread that sets the name member is the one that starts the thread, the synchronization order is guaranteed. (Synchronizes-with implies a Happens-before ordering.)
Note that:
The member name needs only be set before starting the thread: that is, it does not need to be set in the constructor for this synchronizes-with guarantee.
This does not guarantee synchronization ordering - and thus it does not guarantee happens-before or value visibility - between already running threads or threads created elsewhere!
However, final fields do give a much more comfortable feeling (ref. 17.5 Final Field Semantics):
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.
In this case, with final fields, the value is guaranteed to be visible on every thread after the constructor completes. (This guarantee can be violated by "constructor leaks".)
1 In the supplied code the "non-final" name member is only assigned once before the thread is started.
In different, less trivial, programs other synchronization issues may be exposed. This answer examines if removing final alters the correctness of the supplied code.
All that being said, I consider it "good practice" to use both immutable variables (final) and immutable objects - especially when dealing with threads. Instead of needing to know the little arcane details of the JVM, do the safe proven things and strive for obvious correctness over cleverness or "performance".
See also:
Synchronizing an object shared across threads, but not accessed concurrently
When does java thread cache refresh happens?
Java happend before thread start
final variables are immutable, you can not change the value once it is constructed so it does not have concurrency issue.
You will not get the correct value of the field without final.
Maybe the thread got the old value after you changing the value of field.
Check the Visibility of JMM.
Another link of volatile.
Happends-Before Rule.
Happends-Before in JMM.
Could you be looking for an AtomicReference or perhaps volatile? It depends what you mean by thread safe?
// Atomic to allow deeper control of updates.
private AtomicReference<String> name = new AtomicReference<String>();
// Volatile to ensure it is not cached.
private volatile String vName;
public Test(String name) {
this.name.set(name);
this.vName = name;
}
public void start() {
new MyThread().start();
}
private class MyThread extends Thread {
public void run() {
System.out.println(name.get());
System.out.println(vName);
}
}
final doesn't have nothing with multithreading, but you should put final if your fild shouldn't be changed and is initialized in constructor of class. This means that fild can't be changed latter.
since String is immutable and you declare the field final ,with all threads accessing it after the field assignment, then surely there will be no concurrent issues since the field would be used only for Read operation,in contrast to the case where StringBuilder were used.
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.)