Java Thread-safe State Design Pattern

Thread-safe State


Apart from the things mentioned here, this pattern also conveys the intent and benefits of the GoF State pattern, being an extension thereof. The term "behaviour" is interpreted more strictly so that an object is always considered to change its behaviour when its state changes.

Intent


Make sure that an object is observable only in a valid consistent state and that transitions between valid consistent states are atomic and side-effects occur if and only if the associated transition occurs validly.

Motivation


Consider a class where behaviour depends on more than one field and/or side-effects occur as a result of certain state-changes. Such behaviour can be very difficult to analyze for thread-safety and the safe classic approach is to synchronize all methods. Such behaviour can also be difficult to analyze for logical correctness, bringing the motivation for the state pattern into play.

The key idea is to leverage the state pattern and store the current state in an AtomicReference. Current state should be represented by an immutable object. State transitions are performed by a compareAndSet (CAS) operation and a retry on failure. For transitions with side-effects, the CAS is performed to a boilerplate blocking state, the side effects performed, the resultant state set and the blocking state released, whereby each thread released from the blocking state retries the attempted operation on the resulting state. The CAS always compares with the "this" reference of the state instance being transitioned from and can only succeed for one thread, all other threads attempting a simultaneous transition have to retry on the new state.

Applicability


Any object that has a method that has a more complex interaction with the object state than one of either a simple get or a simple set (in which case just marking the field volatile is simpler and more performant).

Structure (given as implementation examples)


Delegate all calls to an immutable state instance:
class Implementation implements Interface {
  private final AtomicReference state;

  public ... doSomething(...) {
      return state.get().doSomething(...);
  }

  private class StateA implements Interface {
    private final ... valueX;
    private final ... valueY;

    public ... doSomething(...) {
       .... valueX ... valueY ...
    }
  }
}

Simple state changes performed by CAS or retry:
class Implementation implements Interface {
  private final AtomicReference state;

  public void setX(y) {
      state.get().setX(y);
  }

  private class StateA implements Interface {
    private final ... x;

    public void setX(y) {
       if (!state.compareAndSet(this, new StateA(y))) {
         state.get().setX(y);
       }
    }
  }
}

State changes with side-effects CAS to a blocking state first:
class Implementation implements Interface {
  private final AtomicReference state;

  public void printAndSetX(y) {
      state.get().printAndSetX(y);
  }

  private class StateA implements Interface {
    private final ... x;

    public void printAndSetX(y) {
       BlockingState guard = new BlockingState();
       if (state.compareAndSet(this, guard)) {
         try {
           print(x);
           state.set(new StateA(y));
         } finally {
           guard.release();
         }
       } else {
         state.get().printAndSetX(y);
       }
    }
  }

  private class BlockingState implements Interface {
    private final CountDownLatch latch = new CountDownLatch(1);

    public void printAndSetX(y) {
      try {
        latch.await();
      } catch (InterruptedException e) {
        // Don't care.
      }
      state.get().printAndSetX(y);
    }

    private void release() {
      latch.countDown();
    }
  }
}

Participants



  • Interface - defines the public interface.

  • Implementation - maintains an AtomicReference to current StateImplementation, implements the public interface.

  • StateImplementation - the implementation of the public interface for a particular state.

  • BlockingState - specialized boilerplate StateImplementation that blocks all calls until released and then delegates to the current state.

Collaborations



  • Implementation delegates relevant (usually all) calls to the current StateImplementation.

  • StateImplementation performs state transitions by a state.compareAndSet(this, nextState) or retry the transition on the current state (which is different from "this" since CAS failed) so that each state object can only be transitioned from once.

  • BlockingState blocks all calls until released, thereupon retries on new current StateImplementation.

Consequences



  1. Interactions with the object always occur with a consistent state of the object, the immutability of the state delegate guaranteeing a consistent result of the interaction and each separate interaction is therefore in effect atomic.

  2. State transitions are explicit and atomic.

  3. Performance seems to be as good as or better than a straightforward non-thread-safe implementatin with mutable fields. Performance is better than that of synchronization (compare "optimistic locking" versus "read/write locking") for applicable objects if some interactions do not entail state changes, especially when the object is reachable from more than one thread (even if access is never contended).

Comments

Anonymous said…
Wonderful post, thanks for putting this together! "This is obviously one great post. Thanks for the valuable information and insights you have so provided here. Keep it up!"
---------------------------------------------
Dissertation Writing | Dissertation Advice
Unknown said…
This comment has been removed by the author.
Aria Kerry said…
This comment has been removed by the author.
free google sms said…
Give The world full of loves! The Great Loves will be giving back to Human!
Nursing assistant classes
Magento said…
Thanks for the coding guidelines.Java some times became very critical.Its very informative and easy coding.
Bahrain website design company
Valuable info. A very nice informational blog. Blessings.

HOTEL SUITES IN WASHINGTON DC
Jacob Hubbard said…
I want to say one thing that you have good command on the topic. Your website in very informative. I will keep on coming here to read new articles. Thanks.
dissertation service writing
Unknown said…
I want to say that you have good writing skills. You have explained it well. I admire your work. Thanks for sharing.
essay title
Unknown said…
the implementation of the public interface for a particular state.
dissertation-topics-examples.info
Stephen said…
In the side-effect example, it seems like you drop the request on the floor if the CAS to the guard state fails. Should there be an 'else' clause that delegates to the current state in that case?
Unknown said…
Timber Merchants Bolton
I really appreciate this wonderful post that you have provided for us. I assure this would be beneficial for most of the people.
Kidul Rel said…
I would like to suggest you that please keep sharing such type of information. Thanks. I really found this to much informatics. It is what i was searching for. jual jelly gamat

Popular Posts