gpt4 book ai didi

Java - InheritableThreadLocal 跨线程泄漏数据

转载 作者:行者123 更新时间:2023-12-01 09:38:07 27 4
gpt4 key购买 nike

场景:

我正在运行一个由 Jetty 提供服务的 Java Web 应用程序。我使用 InheritableThreadLocal 在调用 API 时存储一些数据,然后在 API 调用进一步操作(在同一线程中)时访问这些数据。我存储这些数据的方式是:

代码:

public class RequestDataHolder {

protected static final InheritableThreadLocal<RequestData> reqData = new InheritableThreadLocal<RequestData>();

public static void setRequestData(RequestData request) {
reqData.set(request);
}

public static void removeRequestData() {
reqData.remove();
}

public static RequestData getRequestData() {
return (RequestData) reqData.get();
}

}

public class RequestData {
private String requestId;
private String apiStartTime;

// getters and setters
}

问题:

  1. 当两个 API 调用并行发生时,我发现有时 Thread-1 会看到 Thread-2 设置的 RequestData 对象。这里是否存在数据泄露的可能性?
  2. 我是否正确使用静态方法来设置和获取 InheritableThreadLocal?

编辑

我看到一种行为:

  1. Thread-1 在 ITL 中设置 RequestData 并继续。
  2. 线程 2 在 ITL 中设置 RequestData 并继续。
  3. Thread-1 执行对数据库的调用。
  4. 线程 2 正在处理并修改 RequestData。
  5. Thread-1 醒来并搜索 RequestData,但发现设置的 RequestData 是 Thread-2。

当线程执行 I/O 时,Jetty 中的线程管理方式可能会发生什么情况吗?这里是否有可能因为线程重用而出现父子线程?

最佳答案

终于,我解决了这个问题。

推理:

出现这个问题的原因是,尽管 Java 的 InheritableThreadLocal 保证两个线程不会看到彼此的线程,但是在此变量中放入的内容并不能保证免 protected 跨线程可见。

示例:

例如,对象“RequestData”位于堆上。现在考虑这一系列事件:

  1. Thread-1 调用 ITL 上的集合并设置 RequestData 对象
  2. Thread-2 是从 Thread-1 派生的子线程。由于性质的 ITL,线程 2 获取 ITL转移
  3. Thread-2 在 ITL 上执行 get 操作以检索 RequestData。现在,这个对象将具有与设置的对象相同的哈希代码第 1 步。
  4. 因此,如果您修改 Thread-2 中的任何内容,最终都会更新该引用也将在 Thread-1 中可见。

证明推理的示例代码:

    public class Test implements Runnable {

@Override
public void run() {
RequestData requestData = new RequestData();
System.out.println("Thread ID: Setting requestData with hash code:" + requestData.hashCode());
RequestDataHolder.setRequestData(requestData);
Thread child = new Thread(new Runnable() {
@Override
public void run() {
RequestData requestData = RequestDataHolder.getRequestData();
System.out.println("Thread ID: Retrieved requestData with hash code:" + requestData.hashCode());
}
});
child.start();
}

public static void main(String[] args) {
Thread thread = new Thread(new Test());
thread.start();
}

}

关于Java - InheritableThreadLocal 跨线程泄漏数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38679291/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com