我该如何解决这种比赛情况? [英] How do I fix this race condition?
问题描述
我有一个服务器接受具有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");
}
}
(仅供参考,swallowException
是Boolean
,您可以看到我已尝试对其进行同步.)
(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.TRUE
或Boolean.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屋!