AsynchronousByteChannel 的线程含义
AsynchronousByteChannel.read() 表示操作是异步发生的,但是当流结束时会发生什么已达到?是否允许实现在调用 read() 的同一线程中触发完成处理程序?从实现的角度来看,没有理由异步执行此操作,因为我们已经知道结果。类似地,如果用户尝试读取剩余()返回 0 的 ByteBuffer,我们知道读取操作必须返回 0。
我问这个问题是因为我在自己的 AsynchronousByteChannel 实现中遇到了竞争条件。我正在调用一个完成处理程序,该处理程序在操作完成时调用notify() 本身。然后,我调用以下用户代码:
CompletionHandler<?, ?> handler = ...;
synchronized (handler)
{
asyncByteChannel.read(handler);
handler.wait();
}
请注意,用户假设操作完成时将通知处理程序,但由于 read() 实际上同步调用完成处理程序,因此它会在 wait() 之前收到通知,而后者将永远阻塞。
规范是否要求我在单独的线程中更新 CompletionHandler 或者用户是否应该意识到调用 read() 的线程可能会同步执行某些操作?
The Javadoc for AsynchronousByteChannel.read() says the operation takes place asynchronously, but what happens when the end of stream has been reached? Is an implementation allowed to fire the completion handler within the same thread that invoked read()? From the implementation's point of view, there is no reason to carry out this operation asynchronously, because we already know the result. Similarly, if a user attempts to read into a ByteBuffer where remaining() returns 0 we know the read operation must return 0.
I ask because I've run into a race condition in my own AsynchronousByteChannel implementation. I'm invoking a completion handler that invokes notify() on itself when the operation completes. I then invoke the following user code:
CompletionHandler<?, ?> handler = ...;
synchronized (handler)
{
asyncByteChannel.read(handler);
handler.wait();
}
Note the user is assuming that the handler will be notified when the operation completes, but because read() actually invokes the completion-handler synchronously it gets notified before wait() and the latter will block forever.
Does the specification require me to update CompletionHandler in a separate thread or should users be aware of the fact that the thread that invokes read() may carry out some operations synchronously?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
即使在另一个线程上调用处理程序,也不能保证它会在
read
方法返回之后(即在wait()
之后)被调用> 开始了。 (好吧,同步锁似乎保证了这一点。)您应该使用同步和布尔变量来等待和锁定:
...然后您的处理程序会将
finished
变量设置为 true。Even when the handler is invoked on another thread, there is no guarantee it will be invoked after the
read
method returns, i.e. after yourwait()
started. (Okay, the synchronization lock seems to guarantee this.)You should use synchronization and a boolean variable for the waiting and locking:
... and your handler will then set the
finished
variable to true.查看 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 操作立即完成,并且启动线程是其中之一组中的池线程,然后完成处理程序可以由启动线程直接调用。”
Looking at http://www.docjar.com/html/api/sun/nio/ch/AsynchronousSocketChannelImpl.java.html they always update CompletionHandler in a separate thread, but Future is updated in the same thread. Search for variable
hasSpaceToRead
to find the method in question.I'm guessing their line of reasoning goes something like this:
UPDATE: I stand corrected. According to Invoker.invoke() "If the current thread is in the channel group's thread pool then the handler is invoked directly, otherwise it is invoked indirectly."
SOLVED: According to http://download.oracle.com/javase/7/docs/api/java/nio/channels/AsynchronousChannelGroup.html "Where an I/O operation completes immediately, and the initiating thread is one of the pooled threads in the group then the completion handler may be invoked directly by the initiating thread."