类级别,实例级别和局部ThreadLocals

huangapple go评论64阅读模式
英文:

Class level, instance level and local ThreadLocals

问题

我明白类级别的线程局部变量是有道理的。由于与线程相关,我们需要使线程局部变量在该线程中的不同实例和类之间共享。因此,我们需要将它们设置为类级别。如果我们想在同一类的不同实例之间共享线程局部变量,我们可以将它们设为private static。如果我们想在不同类之间共享线程局部变量,我们可以将它们设为public static

Q0. 如果我上面的理解有误,请纠正我。

我对实例作用域(非静态)线程局部变量和局部(定义在某个方法内部)线程局部变量有疑问:

Q1. 是否存在实例作用域(非静态)线程局部变量的有效用例?
Q2. 是否存在局部(定义在某个方法内部)线程局部变量的有效用例?
Q3. 当实例被垃圾回收时,实例作用域(非静态)线程局部变量会被删除吗?
Q4. 当方法返回时,局部(定义在某个方法内部)线程局部变量会被删除吗?

英文:

I understand how class level thread locals makes sense. Being associated with thread, we need thread locals to be shared among different instances and classes across that thread. So we need to make them class level. If we want to share thread local across different instances of same class, we can make them private static. If we want to share thread local across different classes, we can make them public static.

Q0. correct me if am wrong with above

My doubts are about instance scoped (non-static) thread locals and local (defined inside some method) thread locals:

Q1. Is there any valid use case for instance scoped (non-static) thread locals?
Q2. Is there any valid use case for local (defined inside some method) thread locals?
Q3. Are instance scoped (non-static) thread locals deleted when an instance is garbage collected?
Q4. Are local (defined inside some method) thread locals deleted when method returns?

答案1

得分: 2

ThreadLocal在正确实现为静态变量时,实际上对于所有可以访问它的线程,充当了实例变量的角色。即使只有一个ThreadLocal变量,该机制也使得每个线程在其中都有自己的值实例。

因此,

Q1. 不,将实例限定在范围内的ThreadLocal是没有意义的。这并不是说你不能编写会使用实例限定的ThreadLocal的代码,但你需要在开发者心中同时跟踪实例线程的使用,以实现正确的功能。即使你找到了代码可以解决的用例,仍然有更好的方法来处理它。

Q2. 不。因为局部变量永远不会有多个线程访问它,所以它与普通的局部变量没有区别。

Q3. ThreadLocal<>包装器变得不可访问,但实际变量仍然包含在线程的映射中,正如你正确所说。这会导致资源/内存泄漏,因为它在线程停止之前无法清除。

Q4. 与Q3相同,如果你失去了包装器的引用,将会立即发生泄漏。如果你将引用分配到某个地方,那就是一种奇怪的编程方式。方法局部的ThreadLocal变量会是极其令人担忧的代码。

这个类在现代代码(甚至是旧代码)中不是你想要过多使用的东西,而且它与响应式编程不兼容,但如果你确实使用它,用法是直接的。最容易实现为类级别变量的单个ThreadLocal

英文:

ThreadLocal when implemented correctly as a static variable acts essentially as an instance variable for all threads that have access to it. Even though there's a single ThreadLocal variable, the mechanism makes it so that each thread has its own instance of the value in it.

Therefore

Q1. No, it doesn't make sense to have an instance scoped ThreadLocal. This doesn't mean you couldn't write code that would use an instance scoped TL, but you would need to keep track (in your developer mind) of both the instance and the thread being used for correct functionality, that even if you would find a use case that the code would solve, there would be a lot better way to handle it.

Q2. No. As a local variable can never have more than a single thread access it, it would not differ from a regular local variable.

Q3. The ThreadLocal<> wrapper becomes unreachable, but the actual variable is still contained in the thread's map, as you correctly said. This causes a resource/memory leak, as it can't be cleared until the thread stops.

Q4. Same as with Q3, if you lose the wrapper reference, it's an instant leak. If you assign the reference somewhere, it's just weird programming. A method local ThreadLocal variable would be extremely worrying code.

The class is not something you'd want to use too much anyway in modern code (or even older code), and it's not compatible with reactive programming, but if you do use it the usage is straight-forward. A single ThreadLocal most easily implemented as a class level variable.

答案2

得分: 1

Sure, here's the translated content:

Q2. 是否存在在某个方法内部定义的本地(局部)线程局部变量的有效用例?

首先,让我们明确一点。如果你说“一个本地的 Foobar”(对于任何 class Foobar),那么你说的内容并不是完全清楚的。变量可以是“类级别的”(即 static),也可以是“实例级别的”,或者是“局部的”;但是一个 Foobar 实例不是一个变量。Java 程序中的变量只能引用在堆上分配的 Foobar 实例。在程序中,有多个变量引用同一个实例非常容易且很常见。

ThreadLocal 是一个类,ThreadLocal 的实例是堆上的对象。同一个 ThreadLocal 对象可能会被一个 static ThreadLocal 变量引用,同时在一个或多个线程中也可能被局部变量引用。

当你说“一个本地的 ThreadLocal”时,你可能是在谈论一个局部的变量,该变量持有对一个与其他线程共享的 ThreadLocal 实例的引用,-或者- 你可能在谈论一个只被一个局部变量引用的 ThreadLocal 实例。第二种情况是没有意义的,因为该实例无法被多个线程共享。


Q1. 是否存在在实例范围内(非静态)的线程局部变量的有效用例?

也许是的,但我会称之为“代码异味”(即需要仔细审视代码并看看是否可以更好地组织代码的原因)。就我个人而言,我在新代码中从不使用 ThreadLocal。我唯一使用它的情况是在将旧的单线程代码移植到多线程系统时;在我这么做的情况下,涉及的变量总是 static(即类级别)变量。

我个人尽量避免在新代码中使用 static,除非某个函数明确标记为返回对“单例对象”的引用。


Q3., Q4. [...实例何时被删除...]?

一个实例将在程序中不存在引用它的“活动”变量时,有资格被删除。这种情况可能发生在唯一引用它的变量是某个函数的局部变量,并且该函数返回时。第二种情况是,如果唯一引用该实例的变量被赋值为引用其他实例。第三种情况是,如果唯一引用它的是其他对象的实例变量,并且所有这些其他对象本身都有资格被删除。

在大多数 Java 实现中,当实例有资格被删除时,不会立即删除该实例。实际的删除将在稍后的某个时间发生。何时发生取决于 JRE 的 垃圾回收器 所采用的策略,以及程序对对象使用的模式。

英文:

> Q2. Is there any valid use case for local (defined inside some method) thread locals?

First, lets's just be clear. If you say "a local Foobar" (for any class Foobar), then it's not entirely clear what you are talking about. Variables can be "class level" (i.e., static) or "instance level," or "local;" but a Foobar instance is not a variable. The variables in a Java program can only refer to Foobar instances that are allocated on the heap. It's very easy, and very common to have more than one variable in a program refer to the same instance.

ThreadLocal is a class, and instances of ThreadLocal are objects on the heap. The same ThreadLocal object could be referenced by a static ThreadLocal variable and also, at the same time, referenced by local variables in one or more threads.

When you say "a local ThreadLocal," you could be talking about a local variable that holds a reference to a ThreadLocal instance that is shared with other threads, -OR- you could be talking about a ThreadLocal instance that is only referenced by one local variable. The second case would not make any sense because that instance could not be shared by multiple threads.


> Q1. Is there any valid use case for instance scoped (non-static) thread locals?

Maybe so, but I would call it a "code smell." (That is, a reason to look closely at the code and see whether it could be better organized.) I personally would never use ThreadLocal in new code. The only times I have ever used it is, while porting older, single-threaded code into a multi-threaded system; and when I did it, the variables in question always were static (i.e., class level) variables.

I personally try never to use static in new code except in cases where some function is clearly labelled as returning a reference to a "singleton object."


> Q3., Q4. [...when are instances deleted...]?

An instance will be eligible to be deleted when there is no "live" variable in the program that refers to it. One way that can happen is if the only variable that refers to it is a local variable of some function, and that function returns. A second way it can happen is if the only variable that refers to the instance is assigned to refer to some other instance. A third way is if the only references to it are from instance variables of other objects, and all of those other objects are themselves, eligible to be deleted.

In most Java implementations, the instance will not be immediately deleted when it becomes eligible for deletion. The actual deletion will happen some time later. When, depends on the strategies employed by the JRE's garbage collector and on the patterns of object use by the program.

huangapple
  • 本文由 发表于 2020年4月5日 21:56:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/61043734.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定