AsynchronousByteChannel 的线程含义

发布于 2024-11-24 00:23:39 字数 809 浏览 1 评论 0原文

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

゛时过境迁 2024-12-01 00:23:43

即使在另一个线程上调用处理程序,也不能保证它会在 read 方法返回之后(即在 wait() 之后)被调用> 开始了。 (好吧,同步锁似乎保证了这一点。)

您应该使用同步和布尔变量来等待和锁定:

CompletionHandler<?, ?> handler = ...;
synchronized (handler)
{
   asyncByteChannel.read(handler);
   while(!handler.finished) {
     handler.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 your wait() started. (Okay, the synchronization lock seems to guarantee this.)

You should use synchronization and a boolean variable for the waiting and locking:

CompletionHandler<?, ?> handler = ...;
synchronized (handler)
{
   asyncByteChannel.read(handler);
   while(!handler.finished) {
     handler.wait();
   }
}

... and your handler will then set the finished variable to true.

高速公鹿 2024-12-01 00:23:43

查看 http://www.docjar.com/html /api/sun/nio/ch/AsynchronousSocketChannelImpl.java.html 它们总是在单独的线程中更新 CompletionHandler,但 Future 是在同一个线程中更新。搜索变量 hasSpaceToRead 以查找有问题的方法。

我猜他们的推理思路是这样的:

  1. 我们创建返回给用户的 Future,因此在我们返回对象之前他无法与其交互(同步等)。
  2. 用户创建 CompletionHandler,因此我们无法控制实现的操作(据我们所知,我们可能会触发死锁!)。不要冒险,在单独的线程中触发完成处理程序。

更新:我的观点是正确的。根据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:

  1. We create the Future returned to the user so there is no way he's interacting with it (synchronizing, etc.) before we return the object.
  2. The user creates the CompletionHandler, so we have no way of controlling what the implementation does (for all we know, we could trigger a deadlock!). Don't take a chance, fire the completion handler in a separate thread.

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."

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文