0

似乎在实现依赖 java nio 的服务器时,以下做法是标准的:

使用单个线程(和单个选择器)进行读取:

ByteBuffer buffer = . . .
selector.select()
...
channel.read(buffer)
if (isRequestComplete(buffer))
    processRequest(buffer) //will run in a separate thread

void processRequest(ByteBuffer buffer)
    new Thread(new Handler(buffer)).start()

是的,我省略了大量代码

我的问题不是关于从通道中选择/读取的机制,而是在单独的线程而不是选择器线程中读取#buffer 的可见性语义。我在 javadoc 中看不到任何内容,说明从线程 A(上面的“处理程序”)中的 ByteBuffer 读取可以保证看到对线程 B 中的 ByteBuffer 的写入(上面的“选择器”)。
现在,在我看来,上面的代码根本不是多线程安全的,即它是错误的。但是我在许多教程甚至一些代码库中都看到了相同的模式(甚至总是没有提到可见性问题);所以我想知道我是否遗漏了一些明显的东西。

注意:我特别关注“处理程序”线程仅从#buffer读取的情况 - 它从不向其中写入新字节

4

1 回答 1

1

这实际上似乎没问题。您需要证明选择器线程中的写入“发生在处理程序线程中的读取之前”。根据内存可见性规则,同一线程中的动作按程序顺序发生。新线程的创建也建立了happens-before。所以写发生在线程创建之前发生在读取之前。

如果您将其传递给例如ExecutorService.

于 2013-03-17T06:15:11.300 回答