Threading implications of AsynchronousByteChannel

不打扰是莪最后的温柔 提交于 2019-12-10 20:19:15

问题


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?


回答1:


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.




回答2:


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



来源:https://stackoverflow.com/questions/6666659/threading-implications-of-asynchronousbytechannel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!