首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AsynchronousByteChannel的线程含义

AsynchronousByteChannel的线程含义
EN

Stack Overflow用户
提问于 2011-07-12 23:21:21
回答 2查看 1K关注 0票数 3

AsynchronousByteChannel.read()的Javadoc说操作是异步进行的,但是当到达流的末尾时会发生什么呢?是否允许实现在调用read()的同一线程中触发完成处理程序?从实现的角度来看,没有理由异步执行此操作,因为我们已经知道结果。类似地,如果用户试图读入ByteBuffer ()返回0,我们就知道读操作必须返回0。

我之所以这样问,是因为我在自己的AsynchronousByteChannel实现中遇到了竞争条件。我正在调用一个完成处理程序,该处理程序在操作完成时调用notify()。然后,我调用以下用户代码:

代码语言:javascript
复制
CompletionHandler<?, ?> handler = ...;
synchronized (handler)
{
  asyncByteChannel.read(handler);
  handler.wait();
}

注意:用户假设处理程序将在操作完成时收到通知,但因为read()实际上同步地调用完成处理程序,所以它在wait()之前收到通知,而后者将永远阻塞。

该规范是否要求我在单独的线程中更新CompletionHandler,或者用户是否应该意识到调用read()的线程可能会同步执行某些操作?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-07-13 00:50:06

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

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

  1. 我们创建了返回给用户的未来,因此他无法与之交互(同步等)在我们返回object。
  2. 之前,用户创建了CompletionHandler,因此我们无法控制实现所做的事情(就我们所知,我们可能会触发死锁!)不要冒险,在单独的线程中启动完成处理程序。

更新:我承认错误。根据Invoker.invoke()的说法,“如果当前线程在通道组的线程池中,则直接调用处理程序,否则将间接调用。”

解决了:根据http://download.oracle.com/javase/7/docs/api/java/nio/channels/AsynchronousChannelGroup.html:“如果I/O操作立即完成,并且发起线程是组中的池化线程之一,则完成处理程序可以由发起线程直接调用。”

票数 1
EN

Stack Overflow用户

发布于 2011-07-12 23:34:31

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

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

代码语言:javascript
复制
CompletionHandler<?, ?> handler = ...;
synchronized (handler)
{
   asyncByteChannel.read(handler);
   while(!handler.finished) {
     handler.wait();
   }
}

..。然后您的处理程序会将finished变量设置为true。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6666659

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档