[concurrency-interest] Concurrent Serialization Pattern

Kevin Condon conivek at gmail.com
Fri Sep 15 16:28:24 EDT 2006

Oops, sorry -- my tests were with a primitive (transient final int),
but a transient final *object* is left at the default null value after
defaultReadObject() returns.  (Note to self:  Test *exactly* the case
you're trying to prove from now on.)  So none of my previous examples
actually work, since they all rely on the transient final
ReentrantReadWriteLock = ..., which is going to be the default null.

Thomas Hawtin's earlier suggestion of extending a non-serializable
base class that declares the lock as a final variable is the only
working solution thus far, and at times isn't even possible due to
single-inheritance limitations.

Here's a solution using readResolve() that I tested successfully.  It
uses the correct synchronization, and provides a lot of flexibility.
(Credit to coworker Michael Smith who mentioned off-the-cuff, "maybe
you have to use readResolve".)

public class Serial2 implements Serializable {
  private static final long serialVersionUID = 2006091500L;
  private transient final ReentrantReadWriteLock lock =
    new ReentrantReadWriteLock();
  private transient int x;

  public int getX() {
    try {
      return x;
    } finally {

  public void setX(int x) {
    try {
      this.x = x;
    } finally {

  private void writeObject(ObjectOutputStream out) throws IOException {

  private void readObject(ObjectInputStream in)
      throws IOException, ClassNotFoundException {
    // lock is null, so don't invoke this.setX();
    // program order will ensure visibility
    x = in.readInt();

  private Object readResolve() throws ObjectStreamException {
    Serial2 s = new Serial2();
    // lock is null, so don't invoke this.getX();
    // program order will ensure visibility
    return s;

Seems a bit complex and nuanced for serializing such a simple class.


More information about the Concurrency-interest mailing list