5

netty 文档建议在 ChannelHandlers 中使用实例变量来跟踪通道状态。它没有提到您应该使用 volatile 变量或使用任何其他同步技术来确保跨线程有一致的视图。

例如,在每个连接的基础上使用这个处理程序:

class Handler extends SimpleChannelUpstreamHandler {
        int count = 0;

        @Override
        public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
            ++count;
        }
}

我希望来自 netty 线程池的许多不同线程会调用此方法,尽管不是同时调用,并且可能会看到不一致的视图,从而导致计数不准确。

是这样吗?还是在netty内部进行某种同步会导致对计数字段的写入被刷新?

4

2 回答 2

9

如果您的管道中没有执行程序,并且纯粹在 I/O 工作线程中执行处理程序,那么您就可以了,因为 Netty 保证总是从同一个工作线程回调给定的管道实例。

如果您正在向管道添加执行处理程序,那么如果您使用 Netty 的 OrderedMemoryAwareThreadPoolExecutor 就可以了。

如果您从非 Netty 线程访问您的管道,或者您的管道中有一个非 OrderedMemoryAwareThreadPoolExecutor,那么您需要同步。

我建议查看 Netty 用户论坛档案中的以下主题。

http://netty.markmail.org/search/?q=Memory+visibility+in+handlers#query:Memory%20visibility%20in%20handlers+page:1+mid:cmtw5omcxbg67sho+state:results

http://netty.markmail.org/search/?q=Periodic%20TimerTask%20in#query:Periodic%20TimerTask%20in+page:2+mid:vwahepiois4eqwkp+state:results

于 2011-11-30T18:09:44.053 回答
2

当您创建 NettyChannelPipeline时,如果您将相同的实例添加Handler到所有通道,那么是的,多个线程将读取/修改您的数据。

如果您Handler在管道中为每个通道创建一个新实例,如下所示,那么您是安全的,那么一次只有一个线程将访问管道中的处理程序。

ChannelPipeline p = Channels.pipeline();
pipeline.addLast("handler", new Handler());

还可以看看 Netty ChannelLocal,它就像 java 一样ThreadLocal,您可以在每个通道的基础上设置状态

于 2011-11-29T17:58:24.783 回答