为什么来自 'Concurrency in practice' 的 CooperatingNoDeadlock 对同一个监视器使用双重同步?

Why CooperatingNoDeadlock from 'Concurrency in practice' use double synchronized with same monitor?

在书中 java concurrency in practice 你可以找到以下代码(10.6):

class CooperatingNoDeadlock {
    @ThreadSafe
    class Taxi {
        @GuardedBy("this") private Point location, destination;
        private final Dispatcher dispatcher;

        public Taxi(Dispatcher dispatcher) {
            this.dispatcher = dispatcher;
        }

        public synchronized Point getLocation() {
            return location;
        }

        public synchronized void setLocation(Point location) {
            boolean reachedDestination;
            synchronized (this) {
                this.location = location;
                reachedDestination = location.equals(destination);
            }
            if (reachedDestination)
                dispatcher.notifyAvailable(this);
        }

        public synchronized Point getDestination() {
            return destination;
        }

        public synchronized void setDestination(Point destination) {
            this.destination = destination;
        }
    }

   @ThreadSafe
    class Dispatcher {
        @GuardedBy("this") private final Set<Taxi> taxis;
        @GuardedBy("this") private final Set<Taxi> availableTaxis;

        public Dispatcher() {
            taxis = new HashSet<Taxi>();
            availableTaxis = new HashSet<Taxi>();
        }

        public synchronized void notifyAvailable(Taxi taxi) {
            availableTaxis.add(taxi);
        }

        public Image getImage() {
            Set<Taxi> copy;
            synchronized (this) {
                copy = new HashSet<Taxi>(taxis);
            }
            Image image = new Image();
            for (Taxi t : copy)
                image.drawMarker(t.getLocation());
            return image;
        }
    }

    class Image {
        public void drawMarker(Point p) {
        }
    }

}

让我们研究 setLocation 方法:

public synchronized void setLocation(Point location) { //first synchronized
    boolean reachedDestination;
    synchronized (this) { // second synchronized
        this.location = location;
        reachedDestination = location.equals(destination);
    }
    if (reachedDestination)
        dispatcher.notifyAvailable(this);
    }
}

我没看懂,还是同一台显示器双同步没用?

这段代码是我在书中找到的,你可以在这里找到它:

source

这是一个错误。像这样在同一个监视器上嵌套同步是没有用的。

errata引用了这个列表,"p.214: In Listing 10.6, Taxi.setLocation should not be a synchronized method. (The synchronized block in its body is correct, however.)"

请注意,如果将同步放在块上,则当出租车不在目的地时,可以通知调度员有可用的出租车。这似乎是错误的,但在这种特定情况下也许还有其他措施可以解决这个问题。