AsynchronousByteChannel.read()的Javadoc说操作是异步进行的,但是当到达流的末尾时会发生什么呢?是否允许实现在调用read()的同一线程中触发完成处理程序?从实现的角度来看,没有理由异步执行此操作,因为我们已经知道结果。类似地,如果用户试图读入ByteBuffer ()返回0,我们就知道读操作必须返回0。
我之所以这样问,是因为我在自己的AsynchronousByteChannel实现中遇到了竞争条件。我正在调用一个完成处理程序,该处理程序在操作完成时调用notify()。然后,我调用以下用户代码:
CompletionHandler<?, ?> handler = ...;
synchronized (handler)
{
asyncByteChannel.read(handler);
handler.wait();
}注意:用户假设处理程序将在操作完成时收到通知,但因为read()实际上同步地调用完成处理程序,所以它在wait()之前收到通知,而后者将永远阻塞。
该规范是否要求我在单独的线程中更新CompletionHandler,或者用户是否应该意识到调用read()的线程可能会同步执行某些操作?
发布于 2011-07-13 00:50:06
看看http://www.docjar.com/html/api/sun/nio/ch/AsynchronousSocketChannelImpl.java.html,他们总是在一个单独的线程中更新CompletionHandler,但Future在同一个线程中更新。搜索变量hasSpaceToRead以找到有问题的方法。
我猜他们的推理是这样的:
更新:我承认错误。根据Invoker.invoke()的说法,“如果当前线程在通道组的线程池中,则直接调用处理程序,否则将间接调用。”
解决了:根据http://download.oracle.com/javase/7/docs/api/java/nio/channels/AsynchronousChannelGroup.html:“如果I/O操作立即完成,并且发起线程是组中的池化线程之一,则完成处理程序可以由发起线程直接调用。”
发布于 2011-07-12 23:34:31
即使在另一个线程上调用处理程序,也不能保证它会在 read方法返回后被调用,也就是在wait()启动之后。(好的,同步锁似乎保证了这一点。)
您应该使用同步和用于等待和锁定的布尔变量:
CompletionHandler<?, ?> handler = ...;
synchronized (handler)
{
asyncByteChannel.read(handler);
while(!handler.finished) {
handler.wait();
}
}..。然后您的处理程序会将finished变量设置为true。
https://stackoverflow.com/questions/6666659
复制相似问题