Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Added Bookshelf NCCE

...

Code Block
bgColor#ccccff
public final class Race {
  private final Vector<Racer> racers;
  private final Object lock = new Object();
  
  public Race(Vector<Racer> racer) {
    racers = (Vector<Racer>) racer.clone(); 
  }
  
  public boolean addRacer(Racer racer){	  
    return racers.add(racer);
  }
  
  public boolean removeRacer(Racer racer) {
    synchronized(racers.elementAt(racers.indexOf(racer))) { 
      return racers.remove(racer);      
    }
  }
  
  private double getAverageCurrentSpeed(int i, double currentSpeed) { 
    if (i > racers.size()) {
      return currentSpeed / racers.size();
    }
    synchronized(racers.elementAt(i)) {
      currentSpeed += racers.get(i).getCurrentSpeed();
      return getAverageCurrentSpeed(++i, currentSpeed);  
    }
  }

  private double getAverageCurrentDistance(int i, double distance) { 
    if (i > racers.size()) {		 
      return distance / racers.size();
    }     
    synchronized(racers.elementAt(i)) {
      distance += racers.get(i).getDistance();
      return getAverageCurrentDistance(++i, distance);
    }
  }
  
  public void getStatisticsAtSomePointInRace() {
    synchronized(lock) {
      getAverageCurrentSpeed(0, 0.0);
      getAverageCurrentDistance(0, 0.0);
    }
  }
}

Noncompliant Code Example

Code Block
bgColorFFcccc

public class Book {
  private String title;
  private double width;
  private double weight;

  public String getTitle() {
    return title;
  }
  public double getWidth() {
    return width;
  }
  public double getWeight() {
    return weight;
  }
 
  public Book(String title, double width, double weight) {
    this.title = title;
    this.width = width;
    this.weight = weight;
  }
}

public class Bookshelf {
  private final Vector<Book> books = new Vector<Book>();
  
  public boolean addBook(Book book) {
    // lock on last element to prevent race cond with calculation methods
    synchronized(books.lastElement()) {
      return books.add(new Book( book.getTitle(), book.getWidth(), book.getWeight()));
    }
  }
  
  // only one remove can happen at a time
  public final synchronized boolean removeBook(String title) {
    for (int i = 0; i < books.size(); i++) {
      if (books.getTitle().equals( title)) {
        // lock on book to prevent race cond with calculation routines
        synchronized (books.elementAt(i)) {
          return books.remove( i);
        }
      }
    }
    return false; // book not on bookshelf
  }

  
  private double getTotalWidth(int i, double width) { 
    if (i > books.size()) {
      return width;
    }
    synchronized (books.elementAt(i)) {
      numberOfPages += books.get(i).getWidth();
      return getTotalWidth(++i, width);  
    }
  }

  private double getTotalWeight(int i, double weight) { 
    if (i <= -1) {		 
      return weight;
    }     
    synchronized (books.elementAt(i)) {
      weight += books.get(i).getWeight();
      return getTotalWeight(--i, weight);
    }
  }
}

Risk Assessment

Acquiring and releasing locks in the wrong order may result in deadlocks.

...