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);
}
}