java - 为什么来自 'Concurrency in practice' 的 CooperatingNoDeadlock 使用与同一监视器的双同步?

标签 java concurrency deadlock synchronized

在《java并发实践》一书中可以找到以下代码(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引用此 list ,“p.214:在 list 10.6 中,Taxi.setLocation 不应该是同步方法。(但是,其主体中的同步块(synchronized block)是正确的。)”

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

关于java - 为什么来自 'Concurrency in practice' 的 CooperatingNoDeadlock 使用与同一监视器的双同步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42555198/

相关文章:

multithreading - 为什么 UI 框架必须/应该是单线程的?

c# - 为什么 ffmpeg 在进程中随机停止?

java - 使用实体对象进行数据库管理

java - 使用 MongoDB 进行距离计算

java - 发送完所有未决消息后关闭套接字

go - 并发 |协程 |语言 |缓冲阅读器

c++11 - helgrind 不检测 std::mutex 的递归锁定

MySQL INSERT on SELECT 死锁多人游戏

java - 使用ajax将数据发送到java servlet

java - 如何为 Karate 框架指定 SNI header