Home » concurrent-sources » EDU.oswego.cs.dl.util.concurrent » [javadoc | source]

    1   /*
    2     File: SynchronizedVariable.java
    3   
    4     Originally written by Doug Lea and released into the public domain.
    5     This may be used for any purposes whatsoever without acknowledgment.
    6     Thanks for the assistance and support of Sun Microsystems Labs,
    7     and everyone contributing, testing, and using this code.
    8   
    9     History:
   10     Date       Who                What
   11     30Jun1998  dl               Create public version
   12   */
   13   
   14   package EDU.oswego.cs.dl.util.concurrent;
   15   
   16   /**
   17    * Base class for simple,  small classes 
   18    * maintaining single values that are always accessed
   19    * and updated under synchronization. Since defining them for only
   20    * some types seemed too arbitrary, they exist for all basic types,
   21    * although it is hard to imagine uses for some.
   22    * <p>
   23    *   These classes mainly exist so that you do not have to go to the
   24    *   trouble of writing your own miscellaneous classes and methods
   25    *   in situations  including:
   26    *  <ul>
   27    *   <li> When  you need or want to offload an instance 
   28    *    variable to use its own synchronization lock.
   29    *    When these objects are used to replace instance variables, they
   30    *    should almost always be declared as <code>final</code>. This
   31    *    helps avoid the need to synchronize just to obtain the reference
   32    *    to the synchronized variable itself.
   33    *
   34    *    <li> When you need methods such as set, commit, or swap.
   35    *    Note however that
   36    *    the synchronization for these variables is <em>independent</em>
   37    *    of any other synchronization perfromed using other locks. 
   38    *    So, they are not
   39    *    normally useful when accesses and updates among 
   40    *    variables must be coordinated.
   41    *    For example, it would normally be a bad idea to make
   42    *    a Point class out of two SynchronizedInts, even those
   43    *    sharing a lock.
   44    *
   45    *    <li> When defining <code>static</code> variables. It almost
   46    *    always works out better to rely on synchronization internal
   47    *    to these objects, rather  than class locks.
   48    *  </ul>
   49    * <p>
   50    * While they cannot, by nature, share much code,
   51    * all of these classes work in the same way.
   52    * <p>
   53    * <b>Construction</b> <br>
   54    * Synchronized variables are always constructed holding an
   55    * initial value of the associated type. Constructors also
   56    * establish the lock to use for all methods:
   57    * <ul>
   58    *   <li> By default, each variable uses itself as the
   59    *        synchronization lock. This is the most common
   60    *        choice in the most common usage contexts in which
   61    *        SynchronizedVariables are used to split off
   62    *        synchronization locks for independent attributes
   63    *        of a class.
   64    *   <li> You can specify any other Object to use as the
   65    *        synchronization lock. This allows you to
   66    *        use various forms of `slave synchronization'. For
   67    *        example, a variable that is always associated with a
   68    *        particular object can use that object's lock.
   69    * </ul>
   70    * <p>
   71    * <b>Update methods</b><br>
   72    * Each class supports several kinds of update methods:
   73    * <ul>
   74    *   <li> A <code>set</code> method that sets to a new value and returns 
   75    *    previous value. For example, for a SynchronizedBoolean b,
   76    *    <code>boolean old = b.set(true)</code> performs a test-and-set.
   77    * <p>
   78    *   <li> A  <code>commit</code> method that sets to new value only
   79    *    if currently holding a given value.
   80    * 
   81    * For example, here is a class that uses an optimistic update
   82    * loop to recompute a count variable represented as a 
   83    * SynchronizedInt. 
   84    *  <pre>
   85    *  class X {
   86    *    private final SynchronizedInt count = new SynchronizedInt(0);
   87    * 
   88    *    static final int MAX_RETRIES = 1000;
   89    *
   90    *    public boolean recomputeCount() throws InterruptedException {
   91    *      for (int i = 0; i &lt; MAX_RETRIES; ++i) {
   92    *        int current = count.get();
   93    *        int next = compute(current);
   94    *        if (count.commit(current, next))
   95    *          return true;
   96    *        else if (Thread.interrupted()) 
   97    *          throw new InterruptedException();
   98    *      }
   99    *      return false;
  100    *    }
  101    *    int compute(int l) { ... some kind of computation ...  }
  102    *  }
  103    * </pre>
  104    * <p>
  105    *   <li>A <code>swap</code> method that atomically swaps with another 
  106    *    object of the same class using a deadlock-avoidance strategy.
  107    * <p>
  108    *    <li> Update-in-place methods appropriate to the type. All
  109    *    numerical types support:
  110    *     <ul>
  111    *       <li> add(x) (equivalent to return value += x)
  112    *       <li> subtract(x) (equivalent to return value -= x)
  113    *       <li> multiply(x) (equivalent to return value *= x)
  114    *       <li> divide(x) (equivalent to return value /= x)
  115    *     </ul>
  116    *   Integral types also support:
  117    *     <ul>
  118    *       <li> increment() (equivalent to return ++value)
  119    *       <li> decrement() (equivalent to return --value)
  120    *     </ul>
  121    *    Boolean types support:
  122    *     <ul>
  123    *       <li> or(x) (equivalent to return value |= x)
  124    *       <li> and(x) (equivalent to return value &amp;= x)
  125    *       <li> xor(x) (equivalent to return value ^= x)
  126    *       <li> complement() (equivalent to return x = !x)
  127    *     </ul>
  128    *    These cover most, but not all of the possible operators in Java.
  129    *    You can add more compute-and-set methods in subclasses. This
  130    *    is often a good way to avoid the need for ad-hoc synchronized
  131    *    blocks surrounding expressions.
  132    *  </ul>
  133    * <p>
  134    * <b>Guarded methods</b> <br>
  135    *   All <code>Waitable</code> subclasses provide notifications on
  136    *   every value update, and support guarded methods of the form
  137    *   <code>when</code><em>predicate</em>, that wait until the
  138    *   predicate hold,  then optionally run any Runnable action
  139    *   within the lock, and then return. All types support:
  140    *     <ul>
  141    *       <li> whenEqual(value, action)
  142    *       <li> whenNotEqual(value, action)
  143    *     </ul>
  144    *   (If the action argument is null, these return immediately
  145    *   after the predicate holds.)
  146    *   Numerical types also support 
  147    *     <ul>
  148    *       <li> whenLess(value, action)
  149    *       <li> whenLessEqual(value, action)
  150    *       <li> whenGreater(value, action)
  151    *       <li> whenGreaterEqual(value, action)
  152    *     </ul>
  153    *   The Waitable classes are not always spectacularly efficient since they
  154    *   provide notifications on all value changes.  They are
  155    *   designed for use in contexts where either performance is not an
  156    *   overriding issue, or where nearly every update releases guarded
  157    *   waits anyway.
  158    *  <p>
  159    * <b>Other methods</b> <br>
  160    *   This class implements Executor, and provides an <code>execute</code>
  161    *   method that runs the runnable within the lock.
  162    *   <p>
  163    *   All classes except SynchronizedRef and WaitableRef implement
  164    *   <code>Cloneable</code> and <code>Comparable</code>.
  165    *   Implementations of the corresponding
  166    *   methods either use default mechanics, or use methods that closely
  167    *   correspond to their java.lang analogs. SynchronizedRef does not
  168    *   implement any of these standard interfaces because there are
  169    *   many cases where it would not make sense. However, you can
  170    *   easily make simple subclasses that add the appropriate declarations.
  171    *
  172    *  <p>
  173    *
  174    *
  175    *
  176    * <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]
  177    **/
  178   
  179   public class SynchronizedVariable implements Executor {
  180   
  181     protected final Object lock_;
  182   
  183     /** Create a SynchronizedVariable using the supplied lock **/
  184     public SynchronizedVariable(Object lock) { lock_ = lock; }
  185   
  186     /** Create a SynchronizedVariable using itself as the lock **/
  187     public SynchronizedVariable() { lock_ = this; }
  188   
  189     /**
  190      * Return the lock used for all synchronization for this object
  191      **/
  192     public Object getLock() { return lock_; }
  193   
  194     /**
  195      * If current thread is not interrupted, execute the given command 
  196      * within this object's lock
  197      **/
  198   
  199     public void execute(Runnable command) throws InterruptedException {
  200       if (Thread.interrupted()) throw new InterruptedException();
  201       synchronized (lock_) { 
  202         command.run();
  203       }
  204     }
  205   }

Home » concurrent-sources » EDU.oswego.cs.dl.util.concurrent » [javadoc | source]