我该如何解决这种比赛情况? [英] How do I fix this race condition?

查看:89
本文介绍了我该如何解决这种比赛情况?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个服务器接受具有stop()方法的客户端,该方法可以关闭服务器,这导致我要解决的java.nio.AsynchronousCloseException问题. stop()方法是在另一个线程上调用的,这是导致我认为出现竞争状况的原因.

I have a server accepting clients that has a stop() method that closes the server down, which is causing a java.nio.AsynchronousCloseException that I'd like to resolve. The stop() method is called on a different thread, which is what is causing the race condition I believe.

这是我的代码:

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");
    }
}

(仅供参考,swallowExceptionBoolean,您可以看到我已尝试对其进行同步.)

(FYI, swallowException is a Boolean and you can see I've tried synchronizing it.)

似乎stop()方法将swallowException设置为true,然后又返回到false,然后服务器循环中的异常处理程序才有机会访问它.

It looks like the stop() method is setting swallowException to true and then back to false before the exception handler in my server loop has a chance to access it.

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

UPDATE: I introduced a new Object to use as a lock, and used wait()/notify() to fix my issue:

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的对象上进行同步.

In Java, synchronization is done on an object, not on a variable. When you synchronize on swallowException, you synchronize on its value (Boolean.TRUE or Boolean.FALSE). This is not what you want. You should synchronize on the object that contains swallowException.

这篇关于我该如何解决这种比赛情况?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆