java - 我该如何解决这个竞争条件?

标签 java multithreading race-condition

我有一个接受客户端的服务器,该服务器具有一个可关闭服务器的 stop() 方法,这会导致我想要的 java.nio.AsynchronousCloseException解决。 stop() 方法在不同的线程上调用,我认为这就是导致竞争条件的原因。

这是我的代码:

public void run() {
    InetSocketAddress addr = new InetSocketAddress(provider.getConnection(), 12354);
    try {
        server = ServerSocketChannel.open();
        server.configureBlocking(true);
        server.socket().bind(addr);
        parent.setIP(addr.getAddress().getHostAddress().toString());
        password = generatePassword();
        parent.setPassword(password);
        parent.setStatus("Ready.");
    } catch (IOException e) {
        parent.die("Could not start server: " + e.getMessage());
        runner = null;
    }
    while (runner == Thread.currentThread()) {
        try {
            SocketChannel sc = server.accept();
            if (available) {
                session = new ReceiveSession(this, sc, password, addr.getAddress());
                session.start();
                available = false;
            } else {
                new ReceiveBusyHandler(sc).start();
            }
        } catch (IOException e) {
            synchronized (swallowException) {
                if (!swallowException) {
                    parent.showError(e.toString());
                }
                available = true;
            }
        }
    }
}

public void stop() throws IOException {
    synchronized (swallowException) {
        swallowException = true;
        runner = null;
        if (server != null) {
            server.socket().close();
            server.close();
        }

        swallowException = false;
        System.out.println("Server down");
    }
}

(仅供引用,swallowException 是一个 Boolean,您可以看到我已尝试同步它。)

看起来 stop() 方法将 swallowException 设置为 true,然后再设置为 false我的服务器循环中的异常处理程序有机会访问它。

更新:我引入了一个新的Object来用作锁,并使用wait()/notify()来解决我的问题:

public void run() {
        InetSocketAddress addr = new InetSocketAddress(provider.getConnection(), 12354);
        try {
            server = ServerSocketChannel.open();
            server.configureBlocking(true);
            server.socket().bind(addr);
            parent.setIP(addr.getAddress().getHostAddress().toString());
            password = generatePassword();
            parent.setPassword(password);
            parent.setStatus("Ready.");
        } catch (IOException e) {
            parent.die("Could not start server: " + e.getMessage());
            runner = null;
        }
        while (runner == Thread.currentThread()) {
            try {
                SocketChannel sc = server.accept();
                if (available) {
                    session = new ReceiveSession(this, sc, password, addr.getAddress());
                    session.start();
                    available = false;
                } else {
                    new ReceiveBusyHandler(sc).start();
                }
            } catch (IOException e) {
                synchronized (lock) {
                    if (!swallowException) {
                        parent.showError(e.toString());

                    }
                    lock.notify();
                    available = true;
                }
            }
        }
    }

    public void stop() throws IOException {
        synchronized (lock) {
            swallowException = true;
            runner = null;
            if (server != null) {
                server.socket().close();
                server.close();
            }
            while (swallowException) {
                try {
                    lock.wait();
                    swallowException = false;
                } catch (InterruptedException e) {
                }
            }
            //swallowException = false;
            System.out.println("Server down");
        }
    }

最佳答案

在 Java 中,同步是在对象上完成的,而不是在变量上完成的。当您同步 swallowException 时,您同步其值(Boolean.TRUEBoolean.FALSE)。这不是你想要的。您应该在包含 swallowException 的对象上进行同步。

关于java - 我该如何解决这个竞争条件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16261974/

相关文章:

java - 如何从管道分隔文件中提取动态填充的字母数字单词

java - 为什么这个二次方程不会返回负数?

reactjs - 如何根据同一周期的状态有条件地运行 useEffect

c# - c#静态构造函数中的竞争条件

c# - 建议数据结构/同步方法

java - 实例化泛型类型时的警告

java - 有没有办法在Android上振动小于1毫秒?

python - 慢速网络会导致 Python 应用程序使用*更多* CPU 吗?

c++ - 通过引用 "std::lock_guard<mutex>"返回共享对象是否安全?

java - 在多用户聊天 Android 客户端中使用 AsyncTask 是否比扩展连接线程更好?