When I read jsr-133-faq, in question "How do final fields work under the new JMM?", it said:
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}
static void reader() {
if (f != null) {
int i = f.x;
int j = f.y;
}
}
}
The class above is an example of how final fields should be used. A thread executing reader is guaranteed to see the value 3 for f.x, because it is final. It is not guaranteed to see the value 4 for y, because it is not final.
This makes me confused, because the code in writer is not safe publication, thread executing reader may see f is not null, but the constructor of the object witch f referenced is not finished yet, so even if x is final, the thread executing reader can not be guaranteed to see the value 3 for f.x.
This is the place where I'm confused, pls correct me if i am wrong, thank you very much.
This is the whole point, and that is what's great about about final fields in the JMM. Yes, compiler can generally assign a reference to the object before the object is even fully constructed, and this is unsafe publication because the object may be accessed in a partially-constructed state. However, for final fields, the JMM (and the compiler) guarantees that all final fields will be prepared first, before assigning the reference to the object. The publication may still be unsafe and the object still only partially constructed when a new thread accesses it, but at least the final fields will be in their expected state. From chapter 16.3 in Java Concurrency in Practice:
Initialization safety makes visibility guarantees only for the values
that are reachable through final fields as of the time the constructor
finishes. For values reachable through nonfinal fields, or values that
may change after construction, you must use synchronization to ensure
visibility.
I also recommend reading chapter 16.3 for more detail.
Related
... without additional synchronization ? The Tree class below is meant to be accessed by multiple threads (it is a singleton but not implemented via an enum)
class Tree {
private volatile Node root;
Tree() {
root = new Node();
// the threads are spawned _after_ the tree is constructed
}
private final class Node {
short numOfKeys;
}
}
Will updates to the numOfKeys field be visible to reader threads without any explicit synchronization (notice that both readers and writers have to acquire an instance of ReentrantReadWriteLock - same instance for each node - but barring that) ? If not would making numOfKeys volatile suffice ?
Is changing the root as simple as root = new Node() (only a writer thread would change the root, apart from the main thread which calls the Tree constructor)
Related:
multiple fields: volatile or AtomicReference?
Is volatile enough for changing reference to a list?
Are mutable fields in a POJO object threadsafe if stored in a concurrentHashMap?
Using volatile keyword with mutable object
EDIT: interested in post Java 5 semantics
No.
Placing a reference to an object in a volatile field does not affect the object itself in any way.
Once you load the reference to the object from the volatile field, you have an object no different from any other object, and the volatility has no further effect.
The are two question. Let's start with the second.
Assigning newly constructed objects to volatile variables works nicely. Every thread, that reads the volatile variable, will see a fully constructed object. There is no need for further synchronization. This pattern is usually seen in combination with immutable types.
class Tree {
private volatile Node node;
public void update() {
node = new Node(...);
}
public Node get() {
return node;
}
}
Regarding the first question. You can use volatile variables to synchronize access to non-volatile variable. The following listing shows an example. Imagine that the two variables are initialized as shown, and that the two methods are executed concurrently. It is guaranteed, that if the second thread sees the update to foo, it will also see the update to bar.
volatile int foo = 0;
int bar = 0;
void thread1() {
bar = 1;
foo = 1; // write to volatile variable
}
void thread2() {
if (foo == 1) { // read from volatile variable
int r = bar; // r == 1
}
}
However, your example is different. The reading and writing might look as follows. In contrast to the above example, both threads read from the volatile variable. However, read operations on volatile variables do not synchronize with each other.
void thread1() {
Node temp = root; // read from volatile variable
temp.numOfKeys = 1;
}
void thread2() {
Node temp = root; // read from volatile variable
int r = temp.numOfKeys;
}
In other words: If thread A writes to a volatile variable x and thread B reads the value written to x, then after the read operation, thread B will see all write operations of thread A, that occurred before the write to x. But without a write operation to a volatile variable, there is no effect on updates to other variables.
That sounds more complicated than it actually is. Actually, there is only one rule to consider, which you can find in JLS8 §17.4.5:
[..] If all sequentially consistent executions are free of data races, [..] then all executions of the program will appear to be sequentially consistent.
Simply put, a data race exists if two threads can access the same variable at the same time, at least one operation is a write operation, and the variable is non-volatile. Data races can be eliminated by declaring shared variables as volatile. Without data races, there is no problem with visibility of updates.
Below is the code snippet from concurrency in practice.
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);
}
}
//Volatile is not enough to make VolatileCachedFactorizer thread safe? Why we need final specifier in OneValueCache.
public class VolatileCachedFactorizer implements Servlet {
private volatile OneValueCache cache = new OneValueCache(null, null);
//Servlet service method.
public void service(ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = cache.getFactors(i);
//Check factors are null or not.
if (factors == null) {
factors = factor(i);
cache = new OneValueCache(i, factors);
}
encodeIntoResponse(resp, factors);
}
}
What is the use of declaring fields as final in OneValueCache. "volatile OneValueCache cache" makes sure that object is visible to all the other threads and i assume that writes before volatile write is visible to all the other threads.
Final fields make OneValueCache immutable, thereby making it thread safe. They also have special semantics defined by the JLS, in particular, any thread will be able to see the correctly constructed object with the final fields initialized to its only correct value.
If this was not the case, and the fields happened to not be final, other threads might not be able to see the changes, even made in the constructor, because without final fields, there are no construction safety guarantees.
JCIP explains that OneValueCache is only an immutable reference class used to hold to the two bits of data. This is safer than updating two fields in the method, as it is not atomic. Then, OneValueCache is made volatile in the servlet because it needs to be changed, but is an atomic assignment, so no synchronization is needed.
They are two different things.
Generally,
volatile --> Creates a memory barrier which enforces the data in the cache to be flushed and forces data to be read from the main memory. So, all threads can always get the updated data for this particular field.
final -->
for primitives --> specifies that the value cannot change
for non-primitives --> The references cannot change (i.e, reference cannot point to another object).
For an object / field to be immutable, you need to ensure that it is transitively accessible by final fields and a reference of it doesn't escape.
PS : final and immutability are two different concepts. So, if you've heard of immutability, please understand that it is different from final.
It looks like the intention of OneValueCache class is to be immutable so declaring the values to be final just guarantees that at some later stage a programmer doesnt try to extend the class and overwrite the values.
java.lang.String is only effectively immutable. Brian Goetz of "Java Concurrency in Practice" said something like effectively immutable objects will only be thread safe if safely published. Now, say I unsafely publish String like this:
public class MultiThreadingClass {
private String myPath ="c:\\somepath";
//beginmt runs simultaneously on a single instance of MultiThreading class
public void beginmt(){
Holder h = new Holder();
h.setPath(new File(myPath)); //line 6
h.begin();
}
}
public class Holder {
private File path;
public void setPath(File path){
this.path = path;
}
public void begin(){
System.out.println(path.getCanonicalPath()+"some string");
}
}
At the moment that the MultiThreadingClass is initializing with its constructor, it could happen that the File constructor on line 6 may not see the value of myPath.
Then, about three seconds after the construction of the unsafely published String object, threads on MultiThreadingClass are still running. Could there still be a chance that the File constructor may not see the value of myPath?
Your statement that you are asking your question about:
At the moment that the MultiThreadingClass is initializing with its
constructor, it could happen that the File constructor on line 6 may
not see the value of myPath.
The answer is complicated.
You don't need to worry about the char-array value inside the String object. As I mentioned in the comments, because it is a final field that is assigned in the constructors, and because String doesn't pass a reference to itself before assigning the final field, it is always safely published. You don't need to worry about the hash and hash32 fields either. They're not safely published, but they can only have the value 0 or the valid hash code. If they're still 0, the method String.hashCode will recalculate the value - it only leads to other threads recalculating the hashCode when this was already done earlier in a different thread.
The reference myPath in MultiThreadingClass is not safely published, because it is not final. "At the moment that the MultiThreadingClass is initializing with its constructor", but also later, after the constructor completed, other Threads than the thread that ran the constructor may see the value null in myPath rather than a reference to your string.
There's an example in the Java Memory Model section of the Java Language Specification [version 8 linked but this is unchanged since JMM was released in JSR-133]:
Example 17.5-1. final Fields In The Java Memory Model
The program below illustrates how final fields compare to normal fields.
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}
static void reader() {
if (f != null) {
int i = f.x; // guaranteed to see 3
int j = f.y; // could see 0
}
}
}
The class FinalFieldExample has a final int field x and a non-final
int field y. One thread might execute the method writer and another
might execute the method reader.
Because the writer method writes f after the object's constructor
finishes, the reader method will be guaranteed to see the properly
initialized value for f.x: it will read the value 3. However, f.y is
not final; the reader method is therefore not guaranteed to see the
value 4 for it.
This is even likely to happen on a heavily loaded machine with many threads.
Workarounds/solutions:
Make myPath a final field (and don't add constructors that pass out the this reference before assigning the field)
Make myPath a volatile field
Make sure that all threads accessing myPath synchronize on the same monitor object before accessing myPath. For example, by making beginmt a synchronized method, or by any other means.
Could there still be a chance that the File constructor may not see the value of myPath?
Answer is yes it is possible since Java Memory Model guarantees visibility of only final fields
:-
"A new guarantee of initialization safety should be provided. If an object is properly constructed (which means that references to it do not escape during construction), then all threads which see a reference to that object will also see the values for its final fields that were set in the constructor, without the need for synchronization."
JSR 133 Link
However I feel this situation is impossible to recreate (I too had tried earlier a similar theory but ended in vain).
There is a case of unsafe publication/escape of this reference within the constructor which can lead to the scenario of myPath not being initialized properly. An example for this is given in Listing 3.7 of the book you mentioned. Below is an example of making your class this reference to escape in constructor.
public class MultiThreadingClass implements Runnable{
public static volatile MultiThreadingClass unsafeObject;
private String myPath ="c:\\somepath";
public MultiThreadingClass() {
unsafeObject = this;
.....
}
public void beginmt(){
Holder h = new Holder();
h.setPath(new File(myPath)); //line 6
h.begin();
}
}
The above class can cause other threads to access unsafeObject reference even before the myPath is correctly set but again recreating this scenario might be difficult.
... without additional synchronization ? The Tree class below is meant to be accessed by multiple threads (it is a singleton but not implemented via an enum)
class Tree {
private volatile Node root;
Tree() {
root = new Node();
// the threads are spawned _after_ the tree is constructed
}
private final class Node {
short numOfKeys;
}
}
Will updates to the numOfKeys field be visible to reader threads without any explicit synchronization (notice that both readers and writers have to acquire an instance of ReentrantReadWriteLock - same instance for each node - but barring that) ? If not would making numOfKeys volatile suffice ?
Is changing the root as simple as root = new Node() (only a writer thread would change the root, apart from the main thread which calls the Tree constructor)
Related:
multiple fields: volatile or AtomicReference?
Is volatile enough for changing reference to a list?
Are mutable fields in a POJO object threadsafe if stored in a concurrentHashMap?
Using volatile keyword with mutable object
EDIT: interested in post Java 5 semantics
No.
Placing a reference to an object in a volatile field does not affect the object itself in any way.
Once you load the reference to the object from the volatile field, you have an object no different from any other object, and the volatility has no further effect.
The are two question. Let's start with the second.
Assigning newly constructed objects to volatile variables works nicely. Every thread, that reads the volatile variable, will see a fully constructed object. There is no need for further synchronization. This pattern is usually seen in combination with immutable types.
class Tree {
private volatile Node node;
public void update() {
node = new Node(...);
}
public Node get() {
return node;
}
}
Regarding the first question. You can use volatile variables to synchronize access to non-volatile variable. The following listing shows an example. Imagine that the two variables are initialized as shown, and that the two methods are executed concurrently. It is guaranteed, that if the second thread sees the update to foo, it will also see the update to bar.
volatile int foo = 0;
int bar = 0;
void thread1() {
bar = 1;
foo = 1; // write to volatile variable
}
void thread2() {
if (foo == 1) { // read from volatile variable
int r = bar; // r == 1
}
}
However, your example is different. The reading and writing might look as follows. In contrast to the above example, both threads read from the volatile variable. However, read operations on volatile variables do not synchronize with each other.
void thread1() {
Node temp = root; // read from volatile variable
temp.numOfKeys = 1;
}
void thread2() {
Node temp = root; // read from volatile variable
int r = temp.numOfKeys;
}
In other words: If thread A writes to a volatile variable x and thread B reads the value written to x, then after the read operation, thread B will see all write operations of thread A, that occurred before the write to x. But without a write operation to a volatile variable, there is no effect on updates to other variables.
That sounds more complicated than it actually is. Actually, there is only one rule to consider, which you can find in JLS8 §17.4.5:
[..] If all sequentially consistent executions are free of data races, [..] then all executions of the program will appear to be sequentially consistent.
Simply put, a data race exists if two threads can access the same variable at the same time, at least one operation is a write operation, and the variable is non-volatile. Data races can be eliminated by declaring shared variables as volatile. Without data races, there is no problem with visibility of updates.
I was reading book "java concurrency in practice" and end up with some doubts after few pages.
1) Voltile with non premitive data types :
private volatile Student s;
what is significance of volatile when it comes with non premitive data types ? (I think in this case only think that is sure to be visible to all threads is what Strudent object s is pointing currently and it is possible one thread A modifies some internal member of student and that is not visible to other threads. Am I right ??)
2)
Is a variable can be immutable , even if internal members are not declared as final ??
For example :
Class A {
private Set<String> s = new Set();
public A() {
s.add("Moe");
s.add("Larry");
s.add("Curly");
}
}
In this class do we need to make Set s final to make it immutable or this class is still immutable ? (because even in this case we can't change state of object after it is created).
3 ) There is one example in book that shows how to use volatile and immutable class in combination to get synchronization. Before I put that question I have one more doubt.
suppose there is some function like this :
private Student s = new Student;
void func() {
s.func2(); // 1
if(s.isPossible()) { //2
s = new Student(); //3
}
}
a)func2() acess internal members of s. Now consider Thread A entered into func2 after executing line 1 and Thread B same time reassign s with new object. When Thread A resumes
what it will use new object or the old one ? ( suppose s initally points to memory location 100 (old object) and after a new object is assigned it started pointing to 200 (new object)
then when Thread A resumes it will acess address 100 or address 200).
b) If I make s volatile , will it make any difference to above case.
4.) And here is last one
#Immutable
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);
}
}
#ThreadSafe
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); // Position A
if (factors == null) {
factors = factor(i);
cache = new OneValueCache(i, factors); // Position B
}
encodeIntoResponse(resp, factors);
}
}
Accroding to book class "VolatileCachedFactorizer" is thread safe. Here is my reasoning why it is thread safe (Correct me if I am wrong.) Positin A and Position B are
doubtful positions.
Position A : As cache is pointing to immutable object , any function call is safe (right ?).
Position B : It can have two issue
a)Threads see cache improperly initialized . Not possible in this case as immutable object are guaranteed to be properly initialized (right ?).
b)New assigned object not visible to other threads. Not possible is this case as cache is volatile (right ?).
But it is possible thread A call getFactors() and other thread B reassign cache , in this case A will continue to see old object (right ?)
Yes; volatile only applies to the reference it's applied to.
No; objects that happen to be pointed to by final fields do not magically become immutable.
An object with mutable non-public members is only immutable if those members can never be mutated. (obviously)
Found out after some testing all my answers.
volatile only applies to reference. Any object point by volatile object need not to be visible other threads.
Yes final is important. Without it object of class will not be immutable.
Suppose a variable "obj" is pointing to location x(where the actual object is placed) when a function call on obj is started then during function call all member variables will be read from location x even if some other thread assign a different object on "obj".
Assumed explanations for all answers are correct.