java : Question regarding immutable and final - java

I am reading the book Effective Java.
In an item Minimize Mutability , Joshua Bloch talks about making a class immutable.
Don’t provide any methods that modify the object’s state -- this is fine.
Ensure that the class can’t be extended. - Do we really need to do this?
Make all fields final - Do we really need to do this?
For example let's assume I have an immutable class,
class A{
private int a;
public A(int a){
this.a =a ;
}
public int getA(){
return a;
}
}
How can a class which extends from A , compromise A's immutability ?

Like this:
public class B extends A {
private int b;
public B() {
super(0);
}
#Override
public int getA() {
return b++;
}
}
Technically, you're not modifying the fields inherited from A, but in an immutable object, repeated invocations of the same getter are of course expected to produce the same number, which is not the case here.
Of course, if you stick to rule #1, you're not allowed to create this override. However, you cannot be certain that other people will obey that rule. If one of your methods takes an A as a parameter and calls getA() on it, someone else may create the class B as above and pass an instance of it to your method; then, your method will, without knowing it, modify the object.

The Liskov substitution principle says that sub-classes can be used anywhere that a super class is. From the point of view of clients, the child IS-A parent.
So if you override a method in a child and make it mutable you're violating the contract with any client of the parent that expects it to be immutable.

If you declare a field final, there's more to it than make it a compile-time error to try to modify the field or leave it uninitialized.
In multithreaded code, if you share instances of your class A with data races (that is, without any kind of synchronization, i.e. by storing it in a globally available location such as a static field), it is possible that some threads will see the value of getA() change!
Final fields are guaranteed (by the JVM specs) to have its values visible to all threads after the constructor finishes, even without synchronization.
Consider these two classes:
final class A {
private final int x;
A(int x) { this.x = x; }
public getX() { return x; }
}
final class B {
private int x;
B(int x) { this.x = x; }
public getX() { return x; }
}
Both A and B are immutable, in the sense that you cannot modify the value of the field x after initialization (let's forget about reflection). The only difference is that the field x is marked final in A. You will soon realize the huge implications of this tiny difference.
Now consider the following code:
class Main {
static A a = null;
static B b = null;
public static void main(String[] args) {
new Thread(new Runnable() { void run() { try {
while (a == null) Thread.sleep(50);
System.out.println(a.getX()); } catch (Throwable t) {}
}}).start()
new Thread(new Runnable() { void run() { try {
while (b == null) Thread.sleep(50);
System.out.println(b.getX()); } catch (Throwable t) {}
}}).start()
a = new A(1); b = new B(1);
}
}
Suppose both threads happen to see that the fields they are watching are not null after the main thread has set them (note that, although this supposition might look trivial, it is not guaranteed by the JVM!).
In this case, we can be sure that the thread that watches a will print the value 1, because its x field is final -- so, after the constructor has finished, it is guaranteed that all threads that see the object will see the correct values for x.
However, we cannot be sure about what the other thread will do. The specs can only guarantee that it will print either 0 or 1. Since the field is not final, and we did not use any kind of synchronization (synchronized or volatile), the thread might see the field uninitialized and print 0! The other possibility is that it actually sees the field initialized, and prints 1. It cannot print any other value.
Also, what might happen is that, if you keep reading and printing the value of getX() of b, it could start printing 1 after a while of printing 0! In this case, it is clear why immutable objects must have its fields final: from the point of view of the second thread, b has changed, even if it is supposed to be immutable by not providing setters!
If you want to guarantee that the second thread will see the correct value for x without making the field final, you could declare the field that holds the instance of B volatile:
class Main {
// ...
volatile static B b;
// ...
}
The other possibility is to synchronize when setting and when reading the field, either by modifying the class B:
final class B {
private int x;
private synchronized setX(int x) { this.x = x; }
public synchronized getX() { return x; }
B(int x) { setX(x); }
}
or by modifying the code of Main, adding synchronization to when the field b is read and when it is written -- note that both operations must synchronize on the same object!
As you can see, the most elegant, reliable and performant solution is to make the field x final.
As a final note, it is not absolutely necessary for immutable, thread-safe classes to have all their fields final. However, these classes (thread-safe, immutable, containing non-final fields) must be designed with extreme care, and should be left for experts.
An example of this is the class java.lang.String. It has a private int hash; field, which is not final, and is used as a cache for the hashCode():
private int hash;
public int hashCode() {
int h = hash;
int len = count;
if (h == 0 && len > 0) {
int off = offset;
char val[] = value;
for (int i = 0; i < len; i++)
h = 31*h + val[off++];
hash = h;
}
return h;
}
As you can see, the hashCode() method first reads the (non-final) field hash. If it is uninitialized (ie, if it is 0), it will recalculate its value, and set it. For the thread that has calculated the hash code and written to the field, it will keep that value forever.
However, other threads might still see 0 for the field, even after a thread has set it to something else. In this case, these other threads will recalculate the hash, and obtain exactly the same value, then set it.
Here, what justifies the immutability and thread-safety of the class is that every thread will obtain exactly the same value for hashCode(), even if it is cached in a non-final field, because it will get recalculated and the exact same value will be obtained.
All this reasoning is very subtle, and this is why it is recommended that all fields are marked final on immutable, thread-safe classes.

If the class is extended then the derived class may not be immutable.
If your class is immutable, then all fields will not be modified after creation. The final keyword will enforce this and make it obvious to future maintainers.

Adding this answer to point to the exact section of the JVM spec that mentions why member variables need to be final in order to be thread-safe in an immutable class. Here's the example used in the spec, which I think is very clear:
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
}
}
}
Again, from the spec:
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.

Related

Thread-safety-Java

If I use a Collection which is not thread safe and I just do some get on (Add in a static bloc), and the elements which are put in, have thread safe methods, that's thread safe ?
Moreover, "static final" variables are they thread safe ?
In last, the example above are they equals ?
Example 1 :
public class Test {
private static int cpt = 1;
public synchronized void increment(){
i++;
}
}
Example 2 :
public class Test {
private static Data cpt = new Data(1);
public void increment(){
cpt.inc();
}
}
public class Data {
private int compt;
public Data(int cpt){
compt = cpt;
}
public synchronized void inc(){
compt++;
}
}
Example 3 :
public class Test {
private static Data cpt = new Data(1);
public void increment(){
synchronized(cpt){
cpt.inc();
}
}
}
public class Data {
private int compt;
public Data(int cpt){
compt = cpt;
}
public void inc(){
compt++;
}
}
Thanks you very much ! :)
A static final object MAY be thread-safe IF it is IMMUTABLE. If it mutable and does not provide internal thread-safety, it is not thread safe.
As SJuan76 pointed out, example 1 is not thread-safe because you synchronized on the instance this by making the method an instance method. If the method were static it would be thread-safe. It is also considered poor design practice to synchronize on an instance that other code has access to and could also obtain a lock upon. By doing the default synchronize on an instance method, you lock on that instance. Since the caller has a reference to that instance, the caller could also get a synchronized lock on that instance. The same is true (even more so) by making the method static. Then the lock is acquired on the class object, any other code could then acquire a lock on the class, even without a specific instance.
Examples 2 & 3 are equivalently thread-safe as both synchronize on the Data instance that is held privately.
Static Final Variables are they thread safe?
final fields also allow programmers to implement thread-safe immutable objects without synchronization. A thread-safe immutable object is seen as immutable by all threads, even if a data race is used to pass references to the immutable object between threads. This can provide safety guarantees against misuse of an immutable class by incorrect or malicious code. final fields must be used correctly to provide a guarantee of immutability.
Memory that can be shared between threads is called shared memory or heap memory.
All instance fields, static fields, and array elements are stored in heap memory. In this chapter, we use the term variable to refer to both fields and array elements.
Local variables (§14.4), formal method parameters (§8.4.1), and exception handler parameters (§14.20) are never shared between threads and are unaffected by the memory model.
Above information came from here (http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html)
static fields could be thread safe and final fields could be depending on how it is used , so final static could be if used properly.
So final static or final is sort of the same thing in this case:
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
}
}
}
When it comes to threads, thread1 could see 0 for y or 4 because the constructor needs to be fully initialized for y to be 4 and thread1 could have got to y before the constructor did. But for x it is guaranteed.

Final field, reference and safe publication

Consider the following non-traditional implementation of double-check locking that does not use volatile:
public class ValueProvider {
private static State state = new Initial();
public static Value getValue() {
return state.getValue();
}
private static class Initial implements State {
#Override
public synchronized Value getValue() {
if (state instanceof Initial) {
Value value = new Value();
value.x = 1;
value.y = 2;
state = new Initialized(value);
return value;
} else {
return state.getValue();
}
}
}
private static class Initialized implements State {
private final Value value;
private Initialized(Value value) {
this.value = value;
}
#Override
public Value getValue() {
return value;
}
}
private interface State {
Value getValue();
}
public static final class Value {
private int x;
private int y;
public int getX() {
return x;
}
public int getY() {
return y;
}
}
}
Is this code thread-safe ?
Specifically I am asking about the final field and the guarantees it gives, so the question may be reformulated as is that possible for some thread to get a non-initialized instance of Value ?
UPDATE: removed mention about setters, so that only reads are available after publication
Well, besides the fact that your approach is way too complicated as Bohemian ♦ has pointed out, it could work regarding publication. If two threads access getValue() concurrently, only one thread can enter the synchronized block. The other will either be blocked on the synchronized block or see an instance of Initialized with a correctly initialized value field due to the final field initialization guaranty.
However, it still doesn’t work because the instance of class Value is mutable and your comment // getters and setters indicates that the instance will be mutated after construction. In this case the entire final field initialization guaranty is pointless as the Value class is not thread safe. You might be guarded against seeing the default values for x and y but you will never know what values regarding later-on modifications you will see and the values for (x, y) are not necessarily consistent.
No, this is not thread safe. There is no memory barrier on the read of ValueProvider.state and none at all on Value.
The rule of thumb with Java concurrency is that there needs to be a memory barrier on read and a memory barrier on write.
The only ways to add a memory barrier in Java are:
synchronized
volatile
class initialisation (implicit by the jvm)
atomic
unsafe
For most things Hotspot ignores the final keyword, and prefers to infer it itself. However where final does affect the JMM is to do with class construction and inlining. The reordering rules for final fields are covered in the cookbook that you have already mentioned. It does not mention final classes. The cookbook states:
Loads and Stores of final fields act as "normal" accesses
with respect to locks and volatiles, but impose two additional reordering
1) A store of a final field (inside a constructor and, if the field is a reference, any store that this final can reference, cannot be reordered with a subsequent store
2) The initial load (i.e., the very first encounter by a thread) of a final field cannot be reordered with the initial load of the reference to the object containing the final field.

Outcome of this simple java program?

public class NotActuallyImmutable {
private final int x;
public NotActuallyImmutable(int x) {
this.x = x;// line 1
}
public int getX() {
return x;
}
}
public class Mutable extends NotActuallyImmutable {
private int x = 123;
public Mutable(int x) {
super(x);
}
public int getX() {
return x++;
}
}
now in my main class
NotActuallyImmutable n = new Mutable(42); // line2
int x = n.getX();
System.out.println("x is"+x);
I am expecting the output as 42 but it return the output as 123. I am expecting 42 because at line 2 I am making object of class Mutable and then at line 1 I am setting value as 42. so when i do n.getX() I should get the this latest value not the default 123. I know Ii am missing something but not able to figure out the logic behind it?
The problem is that the field x in Mutable and the field x in class NotActuallyImmutable are not the same. The x that is returned by getX() is the one in Mutable (because the getX() that is invoked is Mutable.getX(), not NotActuallyImmutable.getX()).
Note that if you removed the instance field from Mutable, then you would have a compiler error because NotActuallyImmutable.x is private to NotActuallyImmutable and not accessible to any code in Mutable.
If you made NotActuallyImmutable.x a protected field, then Mutable.x would shadow it and you would still have the same behavior. If you removed Mutable.x in this case, you would still have a compiler error because you were trying to increment a final field.
If you remove Mutable.getX(), then the x that would be returned by getX() would be NotActuallyImmutable.x, despite there being another field of the same name in Mutable.
The private int x in Mutable and the private int x in NotActuallyImmutable are completely different fields that just have the same name.
This isn't a problem for the compiler because you can't access a private field from another class. So as far as the compiler is concerned, when you define Mutable, the x in NotActuallyImmutable is invisible and might as well not exist.
It is of course confusing for the programmer. If you rename one of the fields to y (and the getter method to getY) the behaviour seems much more intuitive.
NotActuallyImmutable n = new Mutable(42); // line2
This means you have an object of type NotActuallyImmutable but the instance of created object is Mutable.
so in this code your dealing with Mutable object which will return 123. as the number you passed is saved in NotActuallyImmutable not in Mutable,
n has two different x values which are visible in different contexts, the parent class's private member variable and the child class's private member variable.
NotActuallyImmutable n = new Mutable(42); // line2
Creates a new Mutable. Executes parent(x) which sets the parent class's x to 42.
int x = n.getX();
n is a Mutable instance so this calls Mutable's getX() which returns Mutable's value for x (123) rather than the parent's.
I agree with Nice explanations given in above answers. But to to just brief the final understanding. As i am doing new Mutable(42).getX(), jvm first will look in Mutable object to get the value of X not inside NotActuallyImmutable. If i remove getX() method from Mutable , i get the expected(as per my expectation) value i.e 42.
This example gets messy becoz variable name i.e X is same in parent and child class but good for understanding concept

About reference to object before object's constructor is finished

Every one of you know about this feature of JMM, that sometimes reference to object could receive value before constructor of this object is finished.
In JLS7, p. 17.5 final Field Semantics we can also read:
The usage model for final fields is a simple one: Set the final fields
for an object in that object's constructor; and do not write a
reference to the object being constructed in a place where another
thread can see it before the object's constructor is finished. If this
is followed, then when the object is seen by another thread, that
thread will always see the correctly constructed version of that
object's final fields. (1)
And just after that in JLS the example follows, which demonstrate, how non-final field is not guaranteed to be initialized (1Example 17.5-1.1) (2):
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
}
}
}
Also, in this question-answer Mr. Gray wrote:
If you mark the field as final then the constructor is guaranteed to
finish initialization as part of the constructor. Otherwise you will
have to synchronize on a lock before using it. (3)
So, the question is:
1) According to statement (1) we should avoid sharing reference to immutable object before its constructor is finished
2) According to JLS's given example (2) and conclusion (3) it seems, that we can safely share reference to immutable object before its constructor is finished, i.e. when all its fields are final.
Isn't there some contradiction?
EDIT-1: What I exactly mean. If we will modify class in example such way, that field y will be also final (2):
class FinalFieldExample {
final int x;
final int y;
...
hence in reader() method it will be guaranteed, that:
if (f != null) {
int i = f.x; // guaranteed to see 3
int j = f.y; // guaranteed to see 4, isn't it???
If so, why we should avoid writing reference to object f before it's constructor is finished (according to (1)), when all fields of f are final?
Isn't there some contradiction [in the JLS around constructors and object publishing]?
I believe these are slightly different issues that are not contradictory.
The JLS reference is taking about storing an object reference in a place where other threads can see it before the constructor is finished. For example, in a constructor, you should not put an object into a static field that is used by other threads nor should you fork a thread.
public class FinalFieldExample {
public FinalFieldExample() {
...
// very bad idea because the constructor may not have finished
FinalFieldExample.f = this;
...
}
}
You shouldn't start the thread in a construtor either:
// obviously we should implement Runnable here
public class MyThread extends Thread {
public MyThread() {
...
// very bad idea because the constructor may not have finished
this.start();
}
}
Even if all of your fields are final in a class, sharing the reference to the object to another thread before the constructor finishes cannot guarantee that the fields have been set by the time the other threads start using the object.
My answer was talking about using an object without synchronization after the constructor had finished. It's a slightly different question although similar with regards to constructors, lack of synchronization, and reordering of operations by the compiler.
In JLS 17.5-1 they don't assign a static field inside of the constructor. They assign the static field in another static method:
static void writer() {
f = new FinalFieldExample();
}
This is the critical difference.
In the full example
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
}
}
}
As you can see, f is not set until after the constructor returns. This means f.x is safe because it is final AND the constructor has returned.
In the following example, neither value is guarenteed to be set.
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
f = this; // assign before finished.
}
static void writer() {
new FinalFieldExample();
}
static void reader() {
if (f != null) {
int i = f.x; // not guaranteed to see 3
int j = f.y; // could see 0
}
}
}
According to statement (1) we should avoid sharing reference to immutable object before its constructor is finished
You should not allow a reference to an object escape before it is constructed for a number of reason (immutable or other wise) e.g. the object might throw an Exception after you have store the object.
According to JLS's given example (2) and conclusion (3) it seems, that we can safely share reference to immutable object, i.e. when all its fields are final.
You can safely share a reference to an immutable object between threads after the object has been constructed.
Note: you can see the value of an immutable field before it is set in a method called by a constructor.
Construct exit plays an important role here; the JLS says "A freeze action on final field f of o takes place when c exits". Publishing the reference before/after constructor exit are very different.
Informally
1 constructor enter{
2 assign final field
3 publish this
4 }constructor exit
5 publish the newly constructed object
[2] cannot be reordered beyond constructor exit. so [2] cannot be reordered after [5].
but [2] can be reordered after [3].
Statement 1) does not say what you think it does. If anything, I would rephrase your statement:
1) According to statement (1) we should avoid sharing reference to
immutable object before its constructor is finished
to read
1) According to statement (1) we should avoid sharing reference to
mutable object before its constructor is finished
where what I mean by mutable is an object that has ANY non-final fields or final references to mutable objects. (have to admit I'm not 100% that you need to worry about final references to mutable objects, but I think I'm right...)
To put it another way, you should distinguish between:
final fields (immutable parts of a possibly immutable object)
non-final fields who have to be initialized before anyone interacts with this object
non-final fields that do not have to be initialized before anyone interacts with this object
The second one is the problem spot.
So, you can share references to immutable objects (all fields are final), but you need to use caution with objects that have non-final fields that HAVE to be initialized before the object can be used by anyone.
In other words, for the edited JLS example you posted where both fields are final, int j = f.y; is guaranteed to be final. But what that means is that you do NOT need to avoid writing the reference to object f, because it'll always be in a correctly initialized state before anyone could see it. You do not need to worry about it, the JVM does.

Private constructor to avoid race condition

I am reading the book Java Concurrency in Practice session 4.3.5
#ThreadSafe
public class SafePoint{
#GuardedBy("this") private int x,y;
private SafePoint (int [] a) { this (a[0], a[1]); }
public SafePoint(SafePoint p) { this (p.get()); }
public SafePoint(int x, int y){
this.x = x;
this.y = y;
}
public synchronized int[] get(){
return new int[] {x,y};
}
public synchronized void set(int x, int y){
this.x = x;
this.y = y;
}
}
I am not clear where It says
The private constructor exists to avoid the race condition that would occur if the copy constructor were implemented as this (p.x, p.y); this is an example of the private constructor capture idiom (Bloch and Gafter, 2005).
I understand that it provides a getter to retrieve both x and y at once in a array instead of a separate getter for each, so the caller will see consistent value, but why private constructor ? what's the trick here
There are already a bunch of answers here, but I would really like to dive into some details (as much as my knowledge let's me). I will strongly advise you to run each sample that is present here in the answer to see for yourself how things are happening and why.
To understand the solution, you need to understand the problem first.
Suppose that the SafePoint class actually looks like this:
class SafePoint {
private int x;
private int y;
public SafePoint(int x, int y){
this.x = x;
this.y = y;
}
public SafePoint(SafePoint safePoint){
this(safePoint.x, safePoint.y);
}
public synchronized int[] getXY(){
return new int[]{x,y};
}
public synchronized void setXY(int x, int y){
this.x = x;
//Simulate some resource intensive work that starts EXACTLY at this point, causing a small delay
try {
Thread.sleep(10 * 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.y = y;
}
public String toString(){
return Objects.toStringHelper(this.getClass()).add("X", x).add("Y", y).toString();
}
}
What variables create the state of this object? Just two of them : x,y. Are they protected by some synchronization mechanism? Well they are by the intrinsic lock, through the synchronized keyword - at least in the setters and getters. Are they 'touched' anywhere else? Of course here:
public SafePoint(SafePoint safePoint){
this(safePoint.x, safePoint.y);
}
What you are doing here is reading from your object. For a class to be Thread safe, you have to coordinate read/write access to it, or synchronize on the same lock. But there is no such thing happening here. The setXY method is indeed synchronized, but the clone constructor is not, thus calling these two can be done in a non thread-safe way. Can we brake this class?
Let's try this out:
public class SafePointMain {
public static void main(String[] args) throws Exception {
final SafePoint originalSafePoint = new SafePoint(1,1);
//One Thread is trying to change this SafePoint
new Thread(new Runnable() {
#Override
public void run() {
originalSafePoint.setXY(2, 2);
System.out.println("Original : " + originalSafePoint.toString());
}
}).start();
//The other Thread is trying to create a copy. The copy, depending on the JVM, MUST be either (1,1) or (2,2)
//depending on which Thread starts first, but it can not be (1,2) or (2,1) for example.
new Thread(new Runnable() {
#Override
public void run() {
SafePoint copySafePoint = new SafePoint(originalSafePoint);
System.out.println("Copy : " + copySafePoint.toString());
}
}).start();
}
}
The output is easily this one:
Copy : SafePoint{X=2, Y=1}
Original : SafePoint{X=2, Y=2}
This is logic, because one Thread updates=writes to our object and the other is reading from it. They do not synchronize on some common lock, thus the output.
Solution?
synchronized constructor so that the read will synchronize on the same lock, but Constructors in Java can not use the synchronized keyword - which is logic of course.
may be use a different lock, like Reentrant lock (if the synchronized keyword can not be used). But it will also not work, because the first statement inside a constructor must be a call to this/super. If we implement a different lock then the first line would have to be something like this:
lock.lock() //where lock is ReentrantLock, the compiler is not going to allow this for the reason stated above.
what if we make the constructor a method? Of course this will work!
See this code for example
/*
* this is a refactored method, instead of a constructor
*/
public SafePoint cloneSafePoint(SafePoint originalSafePoint){
int [] xy = originalSafePoint.getXY();
return new SafePoint(xy[0], xy[1]);
}
And the call would look like this:
public void run() {
SafePoint copySafePoint = originalSafePoint.cloneSafePoint(originalSafePoint);
//SafePoint copySafePoint = new SafePoint(originalSafePoint);
System.out.println("Copy : " + copySafePoint.toString());
}
This time the code runs as expected, because the read and the write are synchronized on the same lock, but we have dropped the constructor. What if this were not allowed?
We need to find a way to read and write to SafePoint synchronized on the same lock.
Ideally we would want something like this:
public SafePoint(SafePoint safePoint){
int [] xy = safePoint.getXY();
this(xy[0], xy[1]);
}
But the compiler does not allow this.
We can read safely by invoking the *getXY method, so we need a way to use that, but we do not have a constructor that takes such an argument thus - create one.
private SafePoint(int [] xy){
this(xy[0], xy[1]);
}
And then, the actual invokation:
public SafePoint (SafePoint safePoint){
this(safePoint.getXY());
}
Notice that the constructor is private, this is because we do not want to expose yet another public constructor and think again about the invariants of the class, thus we make it private - and only we can invoke it.
The private constructor is an alternative to:
public SafePoint(SafePoint p) {
int[] a = p.get();
this.x = a[0];
this.y = a[1];
}
but allows constructor chaining to avoid duplication of the initialization.
If SafePoint(int[]) were public then the SafePoint class couldn't guarantee thread-safety because the contents of the array could be modified, by another thread holding a reference to the same array, between the values of x and y being read by the SafePoint class.
Constructors in Java can not be synchronized.
We can not implement public SafePoint(SafePoint p) as { this (p.x, p.y); } because
As we are not synchronized(and can't as we are in the constructor),
during the execution of the constructor, someone may be calling SafePoint.set() from the different thread
public synchronized void set(int x, int y){
this.x = x; //this value was changed
--> this.y = y; //this value is not changed yet
}
so we will read the object in the inconsistent state.
So instead we create a snapshot in a thread-safe way, and pass it to the private constructor. The stack confinement protects the reference to the array, so there's nothing to worry about.
update
Ha! As for the trick everything is simple - you have missed #ThreadSafe annotation from the book in your example:
#ThreadSafe
public class SafePoint { }
so, if the constructor which takes int array as an argument will be public or protected, the class will no longer be thread-safe, because the content of the array may change the same way as the SafePoint class(i.e. someone may change it during the constructor execution)!
I understand that it provides a getter to retrieve both x and y at once in a array instead of a separate getter for each, so the caller will see consistent value, but why private constructor ? what's the trick here?
What we want here is chaining of constructor calls to avoid code duplication. Ideally something like this is what we want:
public SafePoint(SafePoint p) {
int[] values = p.get();
this(values[0], values[1]);
}
But that won't work because we will get a compiler error:
call to this must be first statement in constructor
And we can't use this either:
public SafePoint(SafePoint p) {
this(p.get()[0], p.get()[1]); // alternatively this(p.x, p.y);
}
Because then we have a condition where the values might have been changed between the call to p.get().
So we want to capture the values from SafePoint and chain to another constructor. That is why we will use the private constructor capture idiom and capture the values in a private constructor and chain to a "real" constructor:
private SafePoint(int[] a) {
this(a[0], a[1]);
}
Also note that
private SafePoint (int [] a) { this (a[0], a[1]); }
does not make any sense outside the class. A 2-D point has two values, not arbitrary values like the array suggests. It has no checks for the length of the array nor that it is not null. It is only used within the class and the caller knows it is safe to call with two values from the array.
Purpose of using SafePoint is to always provide a consistent view of x & y.
For example, consider a SafePoint is (1,1). And one thread is trying to read this SafePoint while another thread is trying to modify it to (2,2). Had safe point not been thread safe it would have been possible to see views where the SafePoint would be (1,2) (or (2,1)) which is inconsistent.
First step towards providing a thread safe consistent view is not to provide independent access to x & y; but to provide a method to access them both at same time. Similar contract applies for modifier methods.
At this point if a copy constructor is not implemented inside SafePoint then it is completely. But if we do implement one we need to be careful. Constructors cannot be synchronized. Implementations such as following will expose a inconsistent state because p.x & p.y are being accessed independently.
public SafePoint(SafePoint p){
this.x = p.x;
this.y = p.y;
}
But following will not break thread safety.
public SafePoint(SafePoint p){
int[] arr = p.get();
this.x = arr[0];
this.y = arr[1];
}
In order to reuse code a private constructor that accepts an int array is implemented that delegates to this(x, y). The int array constructor can be made public but then in effect it will be similar to this(x, y).
The constructor is not supposed to be used outside this class. The clients shouldn't be able to build an array and pass it to this constructor.
All the other public constructors imply that the get method of SafePoint will be called.
The private constructor would allow you to build your own in a , probably, Thread unsafe way (i.e. by retrieving the x,y separately, building an array and passing it)
The private SafePoint(int[] a) provides two functionalities:
First, prevent others from using following constructor, becasue other threads can obtain the ref to the array, and may change the array while constructing
int[] arr = new int[] {1, 2};
// arr maybe obtained by other threads, wrong constructor
SafePoint safepoint = new SafePoint(arr);
Second, prevent later programmers from wrongly implementing the copy constructor like following. That's why author said:
The private constructor exists to avoid the race condition that would occur if the copy constructor were implemented as this(p.x, p.y)
//p may be obtined by other threads, wrong constructor
public SafePoint(SafePoint p) { this(p.x, p.y);}
See author's implementation: you don't have to worry p is modified by other threads,as the p.get() return a new copy, also p.get() is guarded by p's this, so p will not changed, even obtained by other threads!
public SafePoint(SafePoint p) {
this(p.get());
}
public synchronized int[] get() {
return new int[] {x, y};
}
What does it mean is, if you did not have a private constructor and you implement copy constructor in following way:
public SafePoint(SafePoint p) {
this(p.x, p.y);
}
Now assume that thread A is having the access to SafePoint p is executing above copy constructor's this(p.x, p.y) instruction and at the unlucky timing another thread B also having access to SafePoint p executes setter set(int x, int y) on SafePoint p. Since your copy constructor is accessing p's x and y instance variable directly without proper locking it could see inconsistent state of SafePoint p.
Where as the private constructor is accessing p's variables x and y through getter which is synchronized so you are guaranteed to see consistent state of SafePoint p.
Our requirement is: we want to have a copy constructor like below (at the same time ensuring class is still thread safe):
public SafePoint(SafePoint p){
// clones 'p' passed a parameter and return a new SafePoint object.
}
Let's try to make the copy constructor then.
Approach 1:
public SafePoint(SafePoint p){
this(p.x, p.y);
}
The problem with above approach is that it will render our class NOT THREAD SAFE
How ?
Because constructor is NOT synchronised, meaning it is possible that two threads can simultaneously act on the same object (one thread might clone this object using it's copy constructor and other thread might invoke object's setter method). And if this happens, the threads that invoked the setter method could have updated the x field (and yet to update the y field) thereby rendering the object in an inconsistent state. Now at this point, if the other thread (which was cloning the object), executes (and it can execute because constructor is not synchronised by intrinsic lock) the copy constructor this(p.x, p.y), p.x would be the new value, while p.y would still be old.
So, our approach is not thread safe, because constructor is not synchronised.
Approach 2: (Trying to make approach 1 thread safe)
public SafePoint(SafePoint p){
int[] temp = p.get();
this(temp[0], temp[1]);
}
This is thread safe, because p.get() is synchronised by intrinsic lock. Thus while p.get() executes, other thread could not execute the setter because both getter and setter are guarded by the same intrinsic lock.
But unfortunately the compiler won't allow us do this because this(p.x, p.y) should be the first statement.
This brings us to our final approach.
Approach 3: (solving compilation issue of approach 2)
public SafePoint(SafePoint p){
this(p.get());
}
private SafePoint(int[] a){
this(a[0], a[1]);
}
With this approach, we are guaranteed that our class is thread safe and we have our copy constructor.
One final question remaining is why is the second constructor private ?
This is simply because we create this constructor just for our internal purpose and we don't want client to create SafePoint object by invoking this method.

Categories