Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: added the vector Racer code snippets as separate NCE/CS for the time being

...

Consequently, while one thread is calculating the average speed or distance, another thread cannot interfere or induce a deadlock. This is because the other thread would first have to synchronize on racers0, which is impossible until the first calculation is complete.

Noncompliant Code Example

Code Block

// Immutable Racer
public final class Racer {
  private final double currentSpeed;
  private final double distanceTraveled; 

  public Racer(double speed, double distance) {
    currentSpeed = speed;
    distanceTraveled = distance;
  }
  
  public double getCurrentSpeed() {
    return currentSpeed;
  }
  
  public double getDistance() {
    return distanceTraveled;
  }
}
Code Block
bgColor#FFcccc

public final class Race {
  private final Vector<Racer> racers;
  
  public Race(Vector<Racer> racer) {
    racers = (Vector<Racer>) racer.clone(); 
  }
  
  public boolean addRacer(Racer racer){
    synchronized(racers) {
      return racers.add(racer);
    }
  }
  
  public boolean removeRacer(Racer racer) {
    synchronized(racers) {
      return racers.remove(racer);  
    }
  }
  
  private double getAverageCurrentSpeed(int i, double currentSpeed) { 
    if (i > racers.size()) {
      return currentSpeed / racers.size();
    }
    currentSpeed += racers.get(i).getCurrentSpeed();
    return getAverageCurrentSpeed(++i, currentSpeed);   	 	  
  }

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

Compliant Solution

Code Block
bgColor#ccccff

public final class Race {
  private final Vector<Racer> racers;
  
  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) {
      return racers.remove(racer);  
    }
  }
  
  private double getAverageCurrentSpeed(int i, double currentSpeed) { 
    if (i > racers.size()) {
      return currentSpeed / racers.size();
    }
    currentSpeed += racers.get(i).getCurrentSpeed();
    return getAverageCurrentSpeed(++i, currentSpeed);   	 	  
  }

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

Risk Assessment

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

...