...
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 |
---|
|
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 |
---|
|
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.
...