NIO2 CompletionHandler 的线程安全

Mal*_*alt 6 java java-memory-model nio2

以下代码是线程安全的吗?如果是这样,什么保证将ByteBuffer实例安全发布到执行 的线程CompletionHandler

AsynchronousSocketChannel channel = ...
ByteBuffer buf = ByteBuffer.allocate(1024);
channel.read(buf, null, new CompletionHandler<Integer, Void>() {

    //"completed" can be executed by a different thread than channel.read()
    public void completed(Integer result, Void attachment) {                
        buf.flip(); //Can buf be safely accessed here? If so, why?   
        //...          
    }

    public void failed(Throwable exc, Void attachment) {
       //...
    }
});
Run Code Online (Sandbox Code Playgroud)

小智 3

\n

对所有 JVM 和所有平台都有效的权威参考

\n
\n

我所知道的唯一这样的权威来源是 javadocs ( 1 , 2 , 3 )。

\n

不幸的是,正如您亲眼所见,它们不包含明确且明确的线程安全保证。

\n

这意味着代码不是线程安全的。

\n
\n

IMO 应该在methodmethod\'s class或\xe2\x80\x94的 javadoc 中给出保证CompletionHandler,然后我们可以确定它们针对所有 JVM 和所有平台实现(并将在将来保持实现) 。

\n

但如果您确实愿意,您可以从不同 javadoc 中的多个位置“编译”线程安全证明:

\n
    \n
  • AsynchronousSocketChannel.read(...):\n
    \n

    handler 参数是读取操作完成(或失败)时调用的完成处理程序。

    \n
    \n
  • \n
  • java.nio.channels:\n
    \n

    异步通道绑定到异步通道组,以达到资源共享的目的。组具有关联的 ExecutorService,任务将提交到该 ExecutorService 以处理 I/O 事件并分派到完成处理程序,这些完成处理程序消耗在组中的通道上执行的异步操作的结果。

    \n
    \n
  • \n
  • ExecutorService:\n
    \n

    内存一致性影响:将 Runnable 或 Callable 任务提交给 ExecutorService 之前线程中的操作发生在该任务采取的任何操作之前

    \n
    \n
  • \n
\n

结果,我们得到 I/O 读取的每个操作都发生在 =>的第一个操作ByteBuffer 之前CompletionHandler,这意味着代码是线程安全的。

\n

IMO 像上面这样的“编译证明”太脆弱了,我个人认为代码不是线程安全的。

\n