Safety

Notes from  Doug Lea: Java Concurrency. 1st Edition - Chapter 2

Problems in interacting Java threads

Fully Synchronized Objects

import java.util.NoSuchElementException;

public class ExpandableArray {
  private Object[] data_; // the elements
  private int size_; // the number of slots used in the array

  public ExpandableArray(int cap) {
    data_ = new Object[cap];
    size_ = 0;
  }

  public synchronized int size() { return size_; }

  public synchronized Object at(int i) // subscripted access
    throws NoSuchElementException {
    if (i < 0 || i >= size_ )
      throw new NoSuchElementException();
    else
      return data_[i];
  }

  public synchronized void append(Object x) { // add at end
    if (size_ >= data_.length) { // need a bigger array
      Object[] olddata = data_;
      data_ = new Object[3 * (size_ + 1) / 2];
      for (int i = 0; i < size_; ++i)
      data_[i] = olddata[i];
    }
    data_[size_++] = x;
  }

  public synchronized void removeLast()
    throws NoSuchElementException {
    if (size_ == 0)
      throw new NoSuchElementException();
    else
    data_[--size_] = null;
  }
 }

Partial Synchronization

public class LinkedCell {
  protected double value_;
  protected LinkedCell next_; // fixed

  public LinkedCell (double v, LinkedCell t) {
    value_ = v; next_ = t;
  }

  public synchronized double value() { return value_; }

  public synchronized void setValue(double v) { value_ = v; }

  public LinkedCell next() { return next_; } // no synch needed

  public double sum() { // add up all element values
    double v = value(); // get value via synchronized accessor
    if (next() != null)
      v += next().sum(); //recursive
    return v;
  }

  public boolean includes(double x) { // search for x
    synchronized(this) { // synch to access value
      if (value_ == x) return true;
    }
    if (next() == null) return false;
    else return next().includes(x);
  }
}

Contained Objects

Managed Ownership

public class PrintService {

  protected PrintService neighbor_ = null; // node to take from
  protected Printer printer_ = null; // unique

  public synchronized void print(String doc) {
    if (printer_ == null) // get printer from neighbor
    printer_ = neighbor_.takePrinter();
    printer_.printDocument(doc);
  }

  synchronized Printer takePrinter() { // called from others
    if (printer_ != null) {
      Printer p = printer_; // implement take protocol
      printer_ = null;
      return p;
    }
    else
     return neighbor_.takePrinter(); // propagate
  }

// initialization methods called only from start-up

  synchronized void setNeighbor(PrintService n) {
    neighbor_ = n;
  }

  synchronized void givePrinter(Printer p) {
    printer_ = p;
  }
 

// initialize a ring of new services

  public synchronized static void startUpServices(int nServices, Printer p) {
    if (nServices <= 0 || p == null)
      throw new IllegalArgumentException();
    PrintService first = new PrintService();
    PrintService pred = first;
    for (int i =1; i < nServices; ++i) {
      PrintService s = new PrintService();
      s.setNeighbor(pred);
      pred = s;
    }
    first.setNeighbor(pred);
    first.givePrinter(p);
  }
}