Goetz's Java Concurrency in Practice, page 41, mentions how this reference can escape during construction. A "don't do this" example:
public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
});
}
}
Here this is "escaping" via the fact that doSomething(e) refers to the enclosing ThisEscape instance. The situation can be fixed by using static factory methods (first construct the plain object, then register the listener) instead of public constructors (doing all the work). The book goes on:
Publishing an object from within its constructor can publish an incompletely constructed object. This is true even if the publication is the last statement in the constructor. If the this reference escapes during construction, the object is considered not properly constructed.
I don't quite get this. If the publication is the last statement in the constructor, hasn't all the constructing work been done before that? How come is this not valid by then? Apparently there's some voodoo going on after that, but what?
The end of a constructor is a special place in terms of concurrency, with respect to final fields. From section 17.5 of the Java Language Specification:
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.
The usage model for final fields is a
simple one. Set the final fields for
an object in that object's
constructor. 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. It will
also see versions of any object or
array referenced by those final fields
that are at least as up-to-date as the
final fields are.
In other words, your listener could end up seeing final fields with their default values if it examines the object in another thread. This wouldn't happen if listener registration happened after the constructor has completed.
In terms of what's going on, I suspect there's an implicit memory barrier at the very end of a constructor, making sure that all threads "see" the new data; without that memory barrier having been applied, there could be problems.
Another problem arises when you subclass ThisEscape, and the child class invokes this consructor. The implicit this reference in the EventListener would have an incompletely constructed object.
There is a small but finite time between the registerListener ending and the constructor returning. Another thread could use come in at that time and attempt to call doSomething(). If the runtime didn't return straight to your code at that time, the object could be in a invalid state.
I'm not sure of java really but one example I can think of is where possibly the runtime relocates the instance before returning to you.
Its a small chance I grant you.
Related
I was recently going through "Java Concurrency in practice" and came across example of Publication and Escape , after going through it several times I still feel that I didn't completely understood the example.
public class ThisEscape{
public ThisEscape(EventSource source){
source.registerListener(
new EventListener(){
public void onEvent(Event e){
doSomething(e);
}
}
)
}
}
ThisEscape illustrates an important special case of Escape - when the this references escapes during construction. When the inner EvenListener instance is publised ,so is the enclosing ThisEsape instance.But and object is in a predictable ,consistent state only after its constructuor return. so publishing an object from within its constructor can publish an incompletely constructed object.This is true even if the publication is the last statement in the constructor.If the this reference escapes during construction, the object is considered not properly constructed.
ThisEscape cosntructor is registering a EventSource with and EventListener where we are specifying an onEvent behaviour passing an Event instance.
But here I assume the order of object construction to be EventListener --> ThisEscape so how the this reference of ThisEscape is being passed here to escape ?
I believe we should refer to this excerpt:
When the inner EvenListener instance is published, so is the enclosing ThisEsape instance.
Which makes me think doSomething() is a method of ThisEscape (otherwise the reference would not escape), meaning ThisEscape is a listener for EventSource, and it registers itself during construction via overriding EventListener's onEvent method.
In simple words, it says: "when a new event occurs, call doSomething()".
At this point the problem is quite simple. Imagine it, we've registered a new listener inside ThisEscape's constructor... and immediately... an event occurs! While one thread is still constructing ThisEscape, another one is already calling doSomething(), which may lead to a very unpredictable result...
I have a code which is as below
class classA {
int sum = 0;
void recursiveMethodA {
sum = sum +1; // For simplicity
}
}
Basically I am doing some operation in a recursive method which runs lets say 10 times and changing state at class level. But this class is not thread safe.
Now in order to make it thread safe I am thinking of a below option.
class class B {
// Public exposed method
public void methodB {
ClassA classA = new ClassA();
classA.recursiveMethodA();
}
}
My logic is that since I am creating object of class A inside a method of class B, it is created on stack instead of heap and hence it is thread safe.
Is this logic correct? Please suggest alternate options.
My logic is that since I am creating object of class A inside a method of class B, it is created on stack instead of heap and hence it is thread safe.
Your logic and/or terminology are not correct. In fact, the instance of ClassA is in the heap. All regular Java objects are created in the heap!
Your code is actually thread-safe, but the correct explanation is as follows:
The object is created, and the only reference to it is assigned to a local variable.
By inspection, no other thread can ever see that variable.
By inspection, the object reference is never passed to another thread; i.e. it is not published.
The points 1., 2., and 3. mean that the object is thread confined1 for its entire lifetime.
Since the object is thread confined, it is not necessary to consider thread-safety.
It is not sufficient to say (just) that a local variable is used:
There are scenarios where another thread can see the value of a local variable; e.g. if a lambda or inner method closure is created and passed to another thread.
It is also necessary to consider that the value in the variable could be passed to another thread.
Finalization and reference processing will be done on another thread. However, this should NOT present a thread-safety concern. (The JLS spec takes care of finalization, and the javadocs for Reference take care of references. In both cases, there is a happens before at the appropriate points.)
1 - This is a fancy way of saying that no other thread can ever see it the object and its reference.
Do you mean classA is thread safe by itself?
No. It is not thread safe by itself. It is thread safe in this particular context. Or more to the point, thread safety is moot in this context ... because the instance is thread confined.
Shouldn't I define the class as thread safe in all the contexts? I don't know how tomorrow it can be used?
That is up to you!
But consider this: a large number of standard Java classes are NOT thread-safe ... by design. Indeed the classic case is StringBuilder which is the non-thread-safe reimplementation of StringBuffer. Others are most of the collection types in java.util!
Basically, you have two choices:
Make a class inherently thread-safe, and accept that this comes with runtime overheads.
Make a class inherently non-thread-safe, and make sure that you only use it ways that deal with this appropriately. (One way is to thread confine the instances. Another is to use some form of external synchronization.)
The simplest way to have a threadsafe function is put keyword "synchronized"
synchronized public void method() {
//do something
}
Goetz's Java Concurrency in Practice, page 41, mentions how this reference can escape during construction. A "don't do this" example:
public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
});
}
}
Here this is "escaping" via the fact that doSomething(e) refers to the enclosing ThisEscape instance. The situation can be fixed by using static factory methods (first construct the plain object, then register the listener) instead of public constructors (doing all the work). The book goes on:
Publishing an object from within its constructor can publish an incompletely constructed object. This is true even if the publication is the last statement in the constructor. If the this reference escapes during construction, the object is considered not properly constructed.
I don't quite get this. If the publication is the last statement in the constructor, hasn't all the constructing work been done before that? How come is this not valid by then? Apparently there's some voodoo going on after that, but what?
The end of a constructor is a special place in terms of concurrency, with respect to final fields. From section 17.5 of the Java Language Specification:
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.
The usage model for final fields is a
simple one. Set the final fields for
an object in that object's
constructor. 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. It will
also see versions of any object or
array referenced by those final fields
that are at least as up-to-date as the
final fields are.
In other words, your listener could end up seeing final fields with their default values if it examines the object in another thread. This wouldn't happen if listener registration happened after the constructor has completed.
In terms of what's going on, I suspect there's an implicit memory barrier at the very end of a constructor, making sure that all threads "see" the new data; without that memory barrier having been applied, there could be problems.
Another problem arises when you subclass ThisEscape, and the child class invokes this consructor. The implicit this reference in the EventListener would have an incompletely constructed object.
There is a small but finite time between the registerListener ending and the constructor returning. Another thread could use come in at that time and attempt to call doSomething(). If the runtime didn't return straight to your code at that time, the object could be in a invalid state.
I'm not sure of java really but one example I can think of is where possibly the runtime relocates the instance before returning to you.
Its a small chance I grant you.
In the classic "Java concurrency in Practice" Brian Goetz uses the following snippet of code to demonstrate how to safely publish an object using a private constructor and a factory method:
public class SafeListener {
private final EventListener listener;
private SafeListener() {
listener = new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
};
}
public static SafeListener newInstance(EventSource source) {
SafeListener safe = new SafeListener();
source.registerListener(safe.listener);
return safe;
}
}
What I can't figure out yet is how this code achieves safe publication through a private constructor.
I am aware that a private constructor is used to prevent instantiation outside of the object but how does that apply to a thread rather than an object? A thread is not necessarily an object and I can't see what stops another thread from acquiring a reference to safe before the constructor finishes execution.
The constructor’s property of being private has nothing to do with the thread-safety. This is an example of the final field publication guaranty. In order for it to work, the this instance of the final field must not escape during the constructor, therefore the factory method takes care of constructing the holder instance first and registering the listener afterwards. It’s natural for applications of the factory pattern to have private constructors and public factory methods but that is not important to achieve the thread-safety here.
It’s all about how JIT and the HotSpot optimizer treat the code when performing the optimizations. They know what final or volatile fields are and what a constructor is. They will obey the limitations to the degree of optimization of such constructs. Most important, they ensure that all writes to an object you store in the final field and the write to the final field itself happen-before the constructor ends so that the final field stores happen-before any effect of the registerListener invocation in your example. Therefore, other threads can’t see the listener reference before its correct initialization.
Note that this is something you should rarely rely on. In your example, if the method registerListener of the EventSource is not thread-safe, still very bad things can happen. On the other hand, if it’s thread-safe, its thread-safety will apply to the listener constructed before the registration as well so the final field guaranty would not be needed.
Point here is to prevent escapement of this till constructor is finished. To this end, constructor is made private and factory method is provided which takes care of registering listener in external code, after object's constructor finished.
An example of thread-safe API.
how does that apply to a thread rather than an object? A thread is not necessarily an object and I can't see what stops another thread from acquiring a reference to safe before the constructor finishes execution.
A Thread is always an object in the java.lang.Thread sense, of course. The pattern should not be applied to a thread itself. Instead, it could be applied for cases where a new Thread has to be started "together" with the construction of an object. Starting the thread IN the constructor can allow the reference to the incompletely constructed object to escape. However, with this pattern, the newly constructed instance is trapped in the newInstance method until its construction is entirely complete.
(Or to put it that way: I can't imagine how another thread should acquire a reference to the safe instance before its construction is complete. Maybe you can give an example how how you think this might happen.)
I would like to known if each instance of a class has its own copy of the methods in that class?
Lets say, I have following class MyClass:
public MyClass {
private String s1;
private String s2;
private String method1(String s1){
...
}
private String method2(String s2){
...
}
}
So if two differents users make an instance of MyClass like:
MyClass instanceOfUser1 = new MyClass();
MyClass instanceOfUser2 = new MyClass();
Does know each user have in his thread a copy of the methods of MyClass? If yes, the instance variables are then thread-safe, as long as only the instance methods manipulate them, right?
I am asking this question because I often read that instance variables are not thread-safe. And I can not see why it should be like that, when each user gets an instance by calling the new operator?
Each object gets its own copy of the class's instance variables - it's static variables that are shared between all instances of a class. The reason that instance variables are not necessarily thread-safe is that they might be simultaneously modified by multiple threads calling unsynchronized instance methods.
class Example {
private int instanceVariable = 0;
public void increment() {
instanceVariable++;
}
}
Now if two different threads call increment at the same then you've got a data race - instanceVariable might increment by 1 or 2 at the end of the two methods returning. You could eliminate this data race by adding the synchronized keyword to increment, or using an AtomicInteger instead of an int, etc, but the point is that just because each object gets its own copy of the class's instance variables does not necessarily mean that the variables are accessed in a thread-safe manner - this depends on the class's methods. (The exception is final immutable variables, which can't be accessed in a thread-unsafe manner, short of something goofy like a serialization hack.)
Issues with multi-threading arise primarily with static variables and instances of a class being accessed at the same time.
You shouldn't worry about methods in the class but more about the fields (meaning scoped at the class level). If multiple references to an instance of a class exist, different execution paths may attempt to access the instance at the same time, causing unintended consequences such as race conditions.
A class is basically a blueprint for making an instance of an object. When the object is instantiated it receives a spot in memory that is accessed by a reference. If more than one thread has a handle to this reference it can cause occurrences where the instance is accessed simultaneously, this will cause fields to be manipulated by both threads.
'Instance Variables are not thread safe' - this statement depends on the context.
It is true, if for example you are talking about Servlets. It is because, Servlets create only one instance and multiple threads access it. So in that case Instance Variables are not thread safe.
In the above simplified case, if you are creating new instance for each thread, then your instance variables are thread safe.
Hope this answers your question
A method is nothing but a set of instructions. Whichever thread calls the method, get a copy of those instructions. After that the execution begins. The method may use local variables which are method and thread-scoped, or it may use shared resources, like static resources, shared objects or other resources, which are visible across threads.
Each instance has its own set of instance variables. How would you detect whether every instance had a distinct "copy" of the methods? Wouldn't the difference be visible only by examining the state of the instance variables?
In fact, no, there is only one copy of the method, meaning the set of instructions executed when the method is invoked. But, when executing, an instance method can refer to the instance on which it's being invoked with the reserved identifier this. The this identifier refers to the current instance. If you don't qualify an instance variable (or method) with something else, this is implied.
For example,
final class Example {
private boolean flag;
public void setFlag(boolean value) {
this.flag = value;
}
public void setAnotherFlag(Example friend) {
friend.flag = this.flag;
}
}
There's only one copy of the bytes that make up the VM instructions for the setFlag() and setAnotherFlag() methods. But when they are invoked, this is set to the instance upon which the invocation occurred. Because this is implied for an unqualified variable, you could delete all the references to this in the example, and it would still function exactly the same.
However, if a variable is qualified, like friend.flag above, the variables of another instance can be referenced. This is how you can get into trouble in a multi-threaded program. But, as long as an object doesn't "escape" from one thread to be visible to others, there's nothing to worry about.
There are many situations in which an instance may be accessible from multiple classes. For example, if your instance is a static variable in another class, then all threads would share that instance, and you can get into big trouble that way. That's just the first way that pops into my mind...