I have a class with a static var like so
private static Object sMyStaticVar;
if i want to assign a value to this var in the constructor I have code like
if(sMyStaticVar == null) sMyStaticVar = new CustomObject(someRuntimeObject);
where someRuntimeObject is an object that is not available at the time my class is loaded and therefore prevents me from declaring my static var like the below
private static Object sMyStaticVar = new CustomObject(someRuntimeObject);
my question is, is the initialization of the static var object in the constructor thread safe? My instincts tell me its not and i should synchronise using the non-runtime class type as the lock, like the below
synchronized(MyClass.class)
{
if(sMyStaticVar == null) sMyStaticVar = new CustomObject(someRuntimeObject);
}
(as opposed to the runTime type obtained from getClass())
but as my instincts are usually wrong I would be grateful if anyone could shed some light on this for me!
If it is static, you should not assign it in the constructor. Make a static initializer method that does that public static synchronized void initialize(someRuntimeObject).
Note the synchronized keyword: it is is the same as synchronizing on MyClass.class
You are right, the following is open to race conditions:
if(sMyStaticVar == null) sMyStaticVar = new CustomObject(someRuntimeObject);
Two threads could check sMyStaticVar at the same time, see null, create two objects, etc...
This means that you need synchronization. You could either synchronize on some existing object (there are multiple choices), or you could create an object just for the prurpose, so that you don't have to share the lock with anyone else, risking unnecessary contention:
private static Object sMyStaticVar;
private static Object sMyStaticVarLock = new Object();
Then, in the constructor:
synchronized(sMyStaticVarLock)
{
if(sMyStaticVar == null) sMyStaticVar = new CustomObject(someRuntimeObject);
}
This syncrhonization is needed, but it's not enough to achieve thread safety.
You also need to ensure visibility of the field's value when you access it. So, you should either declare that field as volatile or add the same synchronization to every access of that field.
Related
I have class designed for lazy initialization and storing objects which creation is not necessary threadsafe. Here is the code:
class SyncTest {
private static final Object NOT_INITIALIZED = new Object();
private Object object;
/**
* It's guaranteed by outer code that creation of this object is thread safe
* */
public SyncTest() {
object = NOT_INITIALIZED;
}
public Object getObject() {
if (object == NOT_INITIALIZED) {
synchronized (NOT_INITIALIZED) {
if (object == NOT_INITIALIZED) {
final Object tmpRef = createObject();
object = tmpRef;
}
}
}
return object;
}
/**
* Creates some object which initialization is not thread safe
* #return required object or NOT_INITIALIZED
* */
private Object createObject() {
//do some work here
}
}
Here final variable tmpRef is used for storing created object before assigning it to checked variable object . This works in tests but I can't say it's correct for sure and won't be optimsed by compiler.
Can this appraoch be used or object field must be declared as volatile?
Also variant with wrapper class was considered where the line
final Object tmpRef = createObject();
must be replaced with this one:
Object tmpRef = new FinalWrapper(createObject()).getVal();
Wrapper class looks like this:
private class FinalWrapper {
private final Object val;
public FinalWrapper(Object val) {
this.val = val;
}
public Object getVal() {
return val;
}
}
Can some of this examples be safely used in multithreaded environment (especially variant with final local field)?
object = NOT_INITIALIZED;
If you envision this as a trick which will avoid the problems of the usual lazy singleton where you would simply have
object = null;
then it is incorrect; your trick didn't win you any thread safety. You cannot beat the standard double-checked idiom with the volatile variable pointing to the lazily initialized object. So my suggestion would be to get rid of the extra complexity, use null, and use volatile.
Answering your comments:
It's guranteed by JMM that calss initialization with only final fields is always threadsafe.
Class initialization is always thread-safe, regardless of the kind of fields. Every usage of the class is guaranteed to see the objects referred by static fields at least as up-to-date as they were at the time that all class init code completed.
Is the same applicable for local final fields?
The object reached by dereferencing a final field will be at least as up-to-date as it was at the time the constructor of the object containing the final field completed. However, in your solution you never even dereference the field, you just check its value. It is strictly equivalent to check for equality to null as to the value of the NOT_INITIALIZED constant.
You should mark the object variable as volatile to guarantee thread safety, also note that this pattern is only safe in Java 1.5 and later.
This is a tricky piece of code, to quote Joshua Bloch:
The idiom is very fast but also complicated and delicate, so don't be
tempted to modify it in any way. Just copy and paste -- normally not a
good idea, but appropriate here
I´m new in Java and I want to know if is necessary to dispose object to free memory when I serialize it? I try to use my serializable object after the serialization and works fine but my goal is don´t get access until desserealize it. Thanks.
Poo p = new Poo();
try {
FileOutputStream g = new FileOutputStream("obj.ser");
ObjectOutputStream stream = new ObjectOutputStream(g);
stream.writeObject(p);
stream.close();
}
catch(Exception e) { e.printStackTrace(); }
p.getInfo(); // works
You can use methods that customize serialisation to invalidate the object (i.e. make the object throw an exception on every call of a non-private method; That way you at least ensure no methods are sucessfully called).
public final class Poo implements Serializable {
private volatile boolean invalid = false;
public String getInfo() {
synchronized (this) {
if (invalid) {
throw new IllegalStateException("Object shouldn't be used until deserialized");
}
}
// do something
}
// do the same to other methods
// if necessary Object methods like equals and hashCode too
private class SerializationProxy implements Serializable {
private Object readResolve() {
Poo.this.invalid = false;
return Poo.this;
}
}
private synchronized Object writeReplace() {
invalid = true;
return new SerializationProxy();
}
}
However if you just want to make the memory avaliable, it suffices to set all references to the object to null. E.g. If there are no static references to p:
p = null;
Which is automatically done at the end of the scope were you declare p (most likely end of the method). Maybe the compiler can even do some optimisation (release object if no longer needed); however I don't know, if the language spec allows this.
EDIT
Made Poo final to prevent inherited classes from overriding & adding methods and ignore the invalid field.
The answer is no, it is not always necessary to "dispose" of an object after serializing it.
If you have a specific reason for "disposing" of the object (whatever that means in the context of your code), then do so. If you have a question about this specific reason, then improve your question, but your question asks in a general sense, and again, in that sense the answer is no.
Serialization is generation of some bytes based on an object in memory. You can do something with these bytes like write them to a file, send them over the network, etc. The original object remains the same.
Disposing of an object to "free up memory" is performed by the garbage collector automatically sometime after the object is no longer accessible to your program. The best you can do is make sure you are not holding any reference to the object. It will then be collected.
These are separate and unrelated concepts.
It is guranteed or not that every thread sees the value of an instance initializer (the expression right to the equal sign of a field) for a non-final field? For example:
class Foo {
private boolean initialized = false; // Initializer
private final Lock lock = new ReentrantLock();
public void initialize() {
lock.lock()
try {
// Is initialized always false for the first call of initialize()?
if (initialized) {
throw new IllegalStateException("already initialized");
}
// ...
initialized = true;
} finally {
lock.unlock();
}
}
}
In that specific case you are fine because false is also the default value for boolean fields. If your instance variable initialisation were:
private boolean initialized = true;
Then you would have no guarantee that a thread would read true.
Note that if the field were static, you would have such a guarantee due to class loading semantics.
Reference: JLS 17.4.4 (emphasis mine)
The write of the default value (zero, false, or null) to each variable synchronizes-with the first action in every thread.
Although it may seem a little strange to write a default value to a variable before the object containing the variable is allocated, conceptually every object is created at the start of the program with its default initialized values.
The same stands for initialzers that is true for referencing fields:
If you want other threads to see its current value you have to use volatile.
volatile is not surefire however: most of the case you have to use synchronized or other means of synchronizing in order to be sure but in this case a volatile will be enough.
Please refer to this question about the usage of volatile and about thread safety.
Another thing is that only one thread can construct an object and the instance initialization is happening when the object is being constructed. You have to taker care however not to let the this reference escape from the constructor.
It seems to me that what you are looking for is a thread-safe way of lazy initialization. Since direct use of low-level classes such as ReentrantLock can be quite hard to do correctly, I would instead recommend the double-check idiom:
private volatile FieldType field = null; // volatile!
public FieldType getField() {
FieldType result = field; // read volatile field only once, after init
if (result == null) {
synchronized(this) {
result = field;
if (result == null) {
result = computeFieldValue();
field = result;
}
}
}
return result;
}
Note that Double-Check locking requires at least Java 1.5. On older versions of Java it was broken.
A non-final field alone is not guaranteed to be correctly seen, unless you have some other protection such as a lock or synchronized block. i.e. in this case it will always be correct due to the way the value is used.
BTW: For simplicity reasons, I suggest you always structure your code so the component is initialized in the constructor. This avoids such issues as checking the objects is not initialised or initialised twice.
In Java, every class implicitly extends the Object class. So, does this mean we can create an object of the Object class ?
public static void main(String[] args) {
Object ob=new Object();
// code here ....
}
When I tried it, it compiled and ran successfully. In that case, can someone please explain when do we generally create an object of the Object class ?
You could instantiate an instance of an Object if you want to do a synchronization lock.
public void SomeClass {
private Object lock = new Object();
private SomeState state;
public void mutateSomeSharedState() {
synchronized(lock) {
//mutate some state
}
}
public SomeState readState() {
synchronized(lock) {
//access state
}
}
}
It might be necessary to do this when this is already used to lock some other state of the same object, or if you want to have your lock be private (ie, no one else can utilize it). Even if it isn't necessary, some people prefer to do things that way. This is merely an example of when someone might do it.
Normally we don't create an object of the Object class directly. Usually, we create instances of direct/indirect subclasses of Object.
A scenario where we create an instance of Object is to create an object to synchronize threads.
Eg:
Object lock = new Object();
//...
synchronize( lock ) {
//...
//...
}
However the Object class is used a lot to describe parameters of methods and of instance variables that may assume values of different classes (polymorphism).
Eg:
void example(Object arg) {
// ...
System.out.println( "example=" + arg.toString() );
}
Object foo = returnObject();
Sometimes the use of Generics may be better than using Object to describe parameters and variables.
For the most part I believe Object is no longer used explicitly.
Since Java's debut of Generics, casting to the Object class is almost non-existent.
Since java.lang.Object is the super most class, it can be substituted with any instance we create. This concept is very useful when you not aware of the type( eg: A method which conditionally returns different types , Collections with multiple types)
Also commonly used when you want to instantiate class from String,or execute a method using reflections.
However, direct usage of Object is getting redundant due to Generics.
Cheers
Satheesh
I've heard about this happening in non thread-safe code due to improperly constructed objects but I really don't have the concept down, even after reading about in in Goetz's book. I'd like to solidify my understanding of this code smell as I maybe doing it and not even realize it. Please provide code in your explanation to make it stick, thanks.
Example : in a constructor, you create an event listener inner class (it has an implicit reference to the current object), and register it to a list of listener.
=> So your object can be used by another thread, even though it did not finish executing its constructor.
public class A {
private boolean isIt;
private String yesItIs;
public A() {
EventListener el = new EventListener() { ....};
StaticListeners.register(el);
isIt = true;
yesItIs = "yesItIs";
}
}
An additional problem that could happen later : the object A could be fully created, made available to all threads, use by another thread ... except that that thread could see the A instance as created, yesItIs with it "yesItIs" value, but not isIt! Believe it or not, this could happen ! What happen is:
=> synchronization is only half about blocking thread, the other half is about inter-thread visibility.
The reason for that Java choice is performance : inter-thread visibility would kill performance if all data would be shared with all threads, so only synchronized data is guaranteed to be shared...
Really simple example:
public class Test
{
private static Test lastCreatedInstance;
public Test()
{
lastCreatedInstance = this;
}
}
This is the reason why double-checked locking doesn't work. The naive code
if(obj == null)
{
synchronized(something)
{
if (obj == null) obj = BuildObject(...);
}
}
// do something with obj
is not safe because the assignment to the local variable can occur before the rest of the construction (constructor or factory method). Thus thread 1 can be in the BuildObject step, when thread 2 enters the same block, detects a non-null obj, and then proceeds to operate on an incomplete object (thread 1 having been scheduled out in mid-call).
public class MyClass{
String name;
public MyClass(String s)
{
if(s==null)
{
throw new IllegalArgumentException();
}
OtherClass.method(this);
name= s;
}
public getName(){ return name; }
}
In the above code, OtherClass.method() is passed an instance of MyClass which is at that point incompletely constructed, i.e. not yet fulfilling the contract that the name property is non-null.
Steve Gilham is correct in his assesment of why double checked locking is broken. If thread A enters that method and obj is null, that thread will begin to create an instance of the object and assign it obj. Thread B can possibly enter while thread A is still instantiating that object (but not completing) and will then view the object as not null but that object's field may not have been initialized. A partially constructed object.
However, the same type of problem can arrise if you allow the keyword this to escape the constructor. Say your constructor creates an instance of an object which forks a thread, and that object accepts your type of object. Now your object may have not be fully initialized, that is some of your fields may be null. A reference to your object by the one you have created in your constructor can now reference you as a non null object but get null field values.
A bit more explanation:
Your constructor can initialize every field in your class, but if you allow 'this' to escape before any of the other objects are created, they can be null (or default primative) when viewed by other threads if 1. They are not declared final or 2. They are not declared volatile
public class Test extends SomeUnknownClass{
public Test(){
this.addListner(new SomeEventListner(){
#Override
void act(){}
});
}
}
After this operation instanse of SomeEventListner will have a link to Test object, as a usual inner class.
More examples can be find here:
http://www.ibm.com/developerworks/java/library/j-jtp0618/index.html
Here's an example of how uninitialized this of OuterClass can be accessed from inside of inner class:
public class OuterClass {
public Integer num;
public OuterClass() {
Runnable runnable = new Runnable() { // might lead to this reference escape
#Override
public void run() {
// example of how uninitialized this of outer class
// can be accessed from inside of inner class
System.out.println(OuterClass.this.num); // will print null
}
};
new Thread(runnable).start();
new Thread().start(); // just some logic to keep JVM busy
new Thread().start(); // just some logic to keep JVM busy
this.num = 8;
System.out.println(this.num); // will print 8
}
public static void main(String[] args) {
new OuterClass();
}
}
Output:
null
8
Pay attention to OuterClass.this.num instruction in the code