0

I have a class that implements Serializable and I protect the invariant of this class via a lock object which is of type Object. Is it okay to make it transient or can it have any unwanted side effects?

Code :

class MyClass implements Serializable{

 private final transient lock = new Object();
  ....
}
Geek
  • 26,489
  • 43
  • 149
  • 227
  • 6
    Yes, that will work. `transient` only impacts serialization. – Gray Mar 26 '13 at 14:01
  • And make sure the lock is `static` too. – Luiggi Mendoza Mar 26 '13 at 14:03
  • Why you want to make lock `transient`? After deserialization you will need some lock to synchronize on your methods. Are you going to initialize it later? Will `final` let that happen? – Pshemo Mar 26 '13 at 14:08
  • @Pshemo what other options for locking do I have? – Geek Mar 26 '13 at 14:16
  • @Luiggi Mendoza: Of course the lock must not be static! The usual intent of such a lock Object is to provide fine grained synchronization for some method, and by sharing the lock across instances of MyClass this would be counteracted! – Gyro Gearless Mar 26 '13 at 14:17

2 Answers2

8

What you should do is use an empty array (even new Object[0]) instead. Empty arrays are serializable whereas new Object() isn't.

Just do:

private final Object lock = new Object[0];

Automatic (de)serialization will work as expected, a lock will be recreated. It might take a little bit more memory than new Object(), but it should be negligible, and serialized space will also increase by a few bytes.

But it is definitely the simplest solution if you want to avoid custom serialization.

Nuno Cruces
  • 1,584
  • 15
  • 18
  • Worked for me. I think this is the most straighforward solution. Potential drawback would be that empty array takes 16 bytes of heap, whereas empty object takes 8. In most circumstances it does not matter and does not warrant removal of `final` and `transient` + `readObject()` implementation. – Alex Pakka May 15 '14 at 01:29
2

This is fine, as long as you recreate the object upon de-serialization so that you have something to synchronize on.

Also, you'll probably have to remove the final modifier.

It's up to you to decide whether this is worth the hassle.

Community
  • 1
  • 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • I do not want to go through the hassle of recreating the lock object upon de-serialization. So I would like to remove both *final* as well as `transient` modifiers. Can I use any built in lock object for this case? – Geek Mar 26 '13 at 14:15
  • @Geek: What are you trying to achieve? – NPE Mar 26 '13 at 14:16
  • I have a class that can be persisted in disk and that class needs to ensure that its shared state is well protected because mutiple threads can access that state at the same time. – Geek Mar 26 '13 at 14:18
  • 1
    @Geek: And you don't want to serialize the lock? – NPE Mar 26 '13 at 14:19
  • I don't mind serializing the lock but since I am using `Object` as the lock , I had to make it transient. – Geek Mar 26 '13 at 14:20
  • @Geek: If you don't mind serializing it, just keep it non-`transient` and you're done. – NPE Mar 26 '13 at 14:21
  • but then I will have a non-transient,non serializable object inside a serializable object. Isn't that code smelly? Or am I missing something obvious here? – Geek Mar 26 '13 at 14:23
  • 3
    @Geek: You are missing the fact that `Object` is perfectly serializable out of the box. – NPE Mar 26 '13 at 14:23
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/26952/discussion-between-geek-and-npe) – Geek Mar 26 '13 at 14:24
  • 1
    @NPE: No, `Object` is not serializable. Try `out.writeObject(new Object())` and it will throw `java.io.NotSerializableException`. – ddekany Feb 07 '15 at 15:08