我有一个接受客户端的服务器,该服务器具有一个可关闭服务器的 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.TRUE
或 Boolean.FALSE
)。这不是你想要的。您应该在包含 swallowException
的对象上进行同步。
关于java - 我该如何解决这个竞争条件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16261974/