在啥情况下 eventloop.inEventLoop() == false?

Posted

技术标签:

【中文标题】在啥情况下 eventloop.inEventLoop() == false?【英文标题】:In what situation does eventloop.inEventLoop() == false?在什么情况下 eventloop.inEventLoop() == false? 【发布时间】:2020-04-21 22:42:24 【问题描述】:

我正在阅读 netty 4 源代码。 eventLoop.inEventLoop() 无处不在。 根据 Netty 在行动:

一个 Channel 在其生命周期内注册一个 EventLoop。 可以将单个 EventLoop 分配给一个或多个 Channel。 一个通道有并且只有一个事件循环/线程。

理论上,eventLoop.inEventLoop() 是为了确保代码块由分配的 eventLoop/thread 执行。此外,如果您从非 io 线程调用某些东西,eventLoop.inEventLoop() 将变为 false,并将由分配的 eventLoop/thread 执行。

例如,以下代码转到未注册通道(分配给事件循环/线程)的 else 块(NiosocketChannel$NioSocketChannelUnsafe(AbstractChannel$AbstractUnsafe).register(EventLoop, ChannelPromise))。

if (eventLoop.inEventLoop()) 
    register0(promise);
 else 
    try 
        eventLoop.execute(new Runnable() 
            @Override
            public void run() 
                register0(promise);
            
        );
     catch (Throwable t) 
...
    

我真的很困惑,eventLoop.inEventLoop() 有什么意义。 eventLoop.inEventLoop() 保护什么?

除了上面那个,你能不能给我一些更具体的实践例子来说明为什么以及如何eventloop.inEventLoop() == false?你调用什么样的代码?你在哪里打电话?代码如何使eventloop.inEventLoop() == false

【问题讨论】:

【参考方案1】:

这种代码确保只有正确的 eventLoop/thread 才能使用/更改 Channel 对象。当只有一个特定线程可以使用Channel 对象时,这解决了许多竞争条件和多线程问题。这与所谓的“线程安全”以及一个类是否被认为是“线程安全”有关。代码如下:

if (amIOnTheCorrectThread()) 
    doTheActualWork(); // I do the work
 else 
   scheduleOnTheCorrectThread.performAction( doTheActualWork(); ); // let him do the work

取决于您是否在正确的线程上,直接完成工作(在正确的线程上)或任务被卸载到正确的线程,以便其他线程完成工作。另一个线程通过无限循环来执行此操作并检查是否有任何新任务要执行。例如,检查io.netty.channel.ThreadPerChannelEventLoop 类的run() 方法:

@Override
protected void run() 
    for (;;) 
        Runnable task = takeTask();
        if (task != null) 
            task.run();
            // [...]
        
    [...]

【讨论】:

我正在开发一个基于 netty 的模块。它启动一个事件循环来接受传入的消息。似乎 inEventLoop() 总是成立。我应该从事件循环之外调用那些包含 inEventLoop() 的方法吗?如果是,为什么以及在哪里? @MalPsycho 如果方法是public,它们可以从其他类调用,也可以从不同的线程调用。此检查可确保在正确的线程上执行操作。 我明白这一点。我只是从未遇到过必须在事件循环之外调用这些方法的情况。你能举一个现实生活中的例子吗?不必是代码,只是一个简单的想法可能真的很有帮助。 @MalPsycho 其他一些类可以引用您的Channel 对象,而这个其他类正在使用线程做其他事情。在某些时候,该线程可能会调用Channel 对象上的方法。为避免竞争条件和线程问题,设置了此保护以确保仅允许负责 eventLoop 的线程执行请求的操作。

以上是关于在啥情况下 eventloop.inEventLoop() == false?的主要内容,如果未能解决你的问题,请参考以下文章

在啥情况下 [ [ UIApplication sharedApplication ] keyWindow ] 返回 nil?

在啥情况下 alloca() 有用?

在啥情况下 [NSDocument fileURL] 可以为零?

在啥情况下 eventloop.inEventLoop() == false?

在啥情况下 viewWillAppear 会被调用?

英语:在啥情况下单词后面加s,在啥情况下加es