本文介绍了Selector.wakeup()和“在发生之前"关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写另一个NIO服务器.有一个选择器线程执行读取,处理(在大多数情况下)和写入(下面的伪代码,不是真正的Java):

Im writing yet another NIO server. There is a selector thread that performs reading, processing (for the most cases) and writing (pseudo-code below, not real Java):

while (true) {
    select();

    for (key : keys) {
        if (isReading(key)) {
            data = read(key.channel());

            result = process(data);

            key.interestOps(OP_WRITE);
        }

        if (isWriting(key)) {
            key.channel().write(result);
        }
    }
}

在大多数情况下,处理是微不足道的,因此应该没问题.但是,在少数情况下,处理很耗时,应将其委派给另一个线程.因此,该线程应在处理完成后以某种方式告诉选择器对OP_WRITE感兴趣.

The processing for the most cases is trivial, so should be fine. However there are (rare) cases, when processing is time-consuming and should be delegated to another thread. Therefore, that thread should somehow tell selector to be interested in OP_WRITE as the processing is done.

如我所见,至少有两种方法可以完成:

As I see there are at least 2 approaches to do:

  1. 使用同步在同一(工作)线程中调用wakeup()和register()以进行写入,以防止发生下一个select()不会导致register()挂起的情况.
  2. 使注册"操作入队,然后在辅助线程中调用wakeup(),以允许选择器线程使该操作出队以注册以在同一线程中写入.

我的问题是:如果选择方法2,是否必须使用线程安全队列实现(例如ConcurrentLinkedQueue)?我怀疑自enqueue()先于happens-before" dequeue()以来,我没有这样做,而该情况由wakeup()调用保证,但是我无法正式证明这一点.

My question is: do I have to use a thread-safe queue implementation (say, ConcurrentLinkedQueue) if I choose method #2? I suspect I dont since enqueue() "happens-before" dequeue() which is guaranteed by wakeup() call, but I cant formally prove it.

请帮助!谢谢!

推荐答案

根据我的评论,您的问题基于谬论.您无需在处理完成后告诉选择器对OP_WRITE感兴趣".您只需在创建响应后就将其写入即可.仅在该写返回零的情况下,才有必要对通道的OP_WRITE中的选择器感兴趣.

As per my comment, your question is founded on a fallacy. You don't need to 'tell the selector to be interested in OP_WRITE as the processing is done'. You just write the response when you've created it. Only in the case where that write returns zero does it become necessary to interest the selector in OP_WRITE for the channel.

为回答您的补充问题,select()参与了三个记录的同步级别. wakeup()没有,但是您通常会跟随wakeup(),在选择器上同步一个块,在该块中,您可以玩选择器下次选择时需要知道的任何内容.这样就完成了所有必要的事前关系.

To answer your supplementary question, select() engages in three documented levels of synchronization. wakeup() doesn't, but you would normally follow wakeup() wih a block synchronized on the selector, inside which you would play with whatever the selector needs to know about next time it selects. This accomplishes all the necessary happens-before relationships.

这篇关于Selector.wakeup()和“在发生之前"关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-03 21:49
查看更多