一尘不染

ThreadLocal是否可以与Tomcat NIO Connector一起安全使用

tomcat

在我的负载测试期间测试Tomcat
NIO连接器时,才想到这一点。我使用了ThreadLocal的功能,另外我使用了Spring,我知道它在很多地方也使用了Spring。

由于NIO连接器每个连接没有线程,因此我担心,如果在清理之前与另一个线程共享ThreadLocal对象,可能会导致很难发现错误。但是,我认为这不是问题,因为它不是我可以找到的书面警告,也没有发现其他与此相关的警告。我假设NIO连接器对服务实际请求的线程没有影响。

在我接受这个假设之前,我希望找到一些具体的证据。


阅读 570

收藏
2020-06-16

共1个答案

一尘不染

只有熟悉Tomcat代码的人才能为您提供具体的答案,但是我会尝试一个木制的:)

首先,您需要清楚是只使用NIO连接器还是在谈论异步servlet。在每种情况下,答案都会略有不同。

需要注意的主要事情是Java没有任何类型的延续,协同例程或线程重新安排。这意味着一旦启动在线程上运行的一段代码, 只有 那段
代码将在线程上运行,直到完成为止。

因此,如果您有:myObject.doSomething();那么doSomething就目前而言,它对该线程具有独占访问权。线程不会切换到其他代码-
不管您使用哪种类型的IO模型。

可能(将会)发生的事情是,不同的线程将被调度为在不同的CPU上运行,但是每个线程将运行一段代码来完成。

所以如果doSomething是:

public static final ThreadLocal<MyClass> VALUE = new ThreadLocal<MyClass>();
public void doSomething() {
  VALUE.set(this);
  try {
    doSomethingElse();
  } finally {
    VALUE.set(null);
  }
}

那么就没有什么可担心的了- doSomethingElse将只运行一个线程,并且将在整个执行过程中将threadlocal设置为正确的值。

因此,简单的NIO连接器应该没有任何区别-
容器将service在servlet上调用方法,该servlet将在单个线程中执行,然后最后完成。只是容器在处理连接时能够以更有效的方式处理IO。

如果您使用的是异步servlet,则有所不同-
在这种情况下,您的servlet可能会针对单个请求多次调用(由于异步模型的工作方式),并且这些调用可能在不同的线程上,因此您可以在您的Servlet调用之间,不会在线程本地存储任何内容。但是对于您的服务方法的一次调用,它仍然可以。

HTH。

2020-06-16