java - ThreadLocal 与 Tomcat NIO Connector 一起使用是否安全

标签 java tomcat nio thread-local

这只是在我的负载测试期间测试 Tomcat NIO 连接器时想到的。我还使用了 ThreadLocal,我还使用了 Spring,我知道它在几个地方也使用了它。

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

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

最佳答案

只有熟悉 Tomcat 代码的人才能给你一个具体的答案,但我会尝试一个木制的 :)

首先,您需要弄清楚您是指简单地使用 NIO 连接器还是指的是 Async 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 连接器应该没有什么区别——容器将调用 servlet 上的 service 方法,servlet 将在单个线程中执行,然后在最后完成。只是容器在处理连接时能够以更有效的方式处理 IO。

如果您使用的是异步 servlet,那么情况会有所不同 - 在这种情况下,您的 servlet 可能会针对单个请求被多次调用(由于异步模型的工作方式),并且这些调用可能在不同的线程上,所以你不能在你的 servlet 调用之间在线程本地存储一些东西。但是对于您的服务方法的单次调用,它仍然没问题。

HTH.

关于java - ThreadLocal 与 Tomcat NIO Connector 一起使用是否安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7925014/

相关文章:

java - 如何将网格从 Blender 3.++ 导入到 javafx?

java - 如何在不更改任何一组的情况下找到两组之间的差异?

spring - 将 Spring(Boot?)添加到现有的 RESTEasy JAX-RS 应用程序

java - JMock 意外调用

java - 无法从套接字读取捕获 -1 响应

bash - 如何使用 tomcat 7 在嵌入式 Web 应用程序中运行 bash 脚本(linux)?

未找到 Java Apache Tomcat 所需资源

Java Files.copy 抛出带有符号链接(symbolic link)的 FileNotFoundException

java - toRealPath 方法的行为(类 java.nio.file.Path)

java - 无法在 Windows 上中断 Java 中的命名管道 channel