4

如果我使用 threadlocal 变量,那么每个线程都会获得该变量的本地副本。我的第一个问题是,如果每个线程都对变量进行变异,变异后的值是否仅保留在其本地副本中?或者在某个时候它也会尝试更新“全局变量”,我们会遇到并发问题?

我的另一个问题是:如果我在一个方法中声明一个变量,那么每个在自己的堆栈中执行该方法的线程都会得到自己的副本。那么声明一个方法级别的变量和让它成为线程本地的一样吗?

4

4 回答 4

3

第一个问题:每个线程更新其线程局部变量的副本,线程之间不共享全局状态。

第二个问题:如果您声明局部变量,它的行为类似于 threadlocal - 每个线程都有自己的副本,但您没有全局访问它,例如在另一种方法中 - 那是 threadlocal 有用的时候。

于 2013-08-29T14:09:04.710 回答
1

查看ThreadLocal<T>对象的最简单方法是作为 a Map<Thread, T>,其中ThreadLocal#get()调用将通过调用Map#get(Thread.currentThread())底层来查找正确的值Map。请注意,这不是实际的实现,而是查看它的最简单方法。

ThreadLocal变量仅作为可以被多个线程同时访问的成员才有用。方法中变量的局部声明只是局部的,因此其他线程无法访问。我不会说它们是“相同的”,但它们都是线程安全的。

典型用法是多线程环境中单例对象的实例成员变量或类的静态成员变量。

大多数情况下,您会看到它们用于在 servlet 环境中传递请求上下文信息。

于 2013-08-29T14:06:51.593 回答
1

如果我使用 threadlocal 变量,那么每个线程都会获得该变量的本地副本

我认为关于变量的本地副本这个术语有些混乱。没有副本。每个线程都有自己的变量;这些是相互独立的。然而,这并不意味着它们不能持有对共享对象的引用。因此,仅使用 threadlocal 变量并不能避免并发问题。

关于你的第二个问题:不。局部变量和线程局部变量是不同的。局部变量在定义它们的块之外是不可访问的。因此,例如,调用相同的方法两次,每次都会产生不同的值。另一方面,只要线程存在,线程局部变量就会保持它们的值。

基本上,线程局部变量是一种用于单个线程的“静态”变量。

于 2013-08-29T14:11:00.067 回答
0

关于 ThreadLocal 变量的一个重点是全局访问。它可以从线程内的任何地方访问。在该线程上下文中调用的任何方法内。

如果你想为一个类的所有实例维护一个变量的单个实例,你将使用静态类成员变量来做到这一点。如果您想在每个线程的基础上维护一个变量的实例,您将使用线程局部变量。ThreadLocal 变量不同于普通变量,因为每个线程都有自己单独初始化的变量实例,它通过 get() 或 set() 方法访问。

假设您正在开发一个多线程代码跟踪器,其目标是唯一标识每个线程在您的代码中的路径。挑战在于您需要跨多个线程协调多个类中的多个方法。如果没有 ThreadLocal,这将是一个复杂的问题。当一个线程开始执行时,它需要生成一个唯一标记以在跟踪器中识别它,然后将该唯一标记传递给跟踪中的每个方法。

使用 ThreadLocal,事情变得更简单了。线程在执行开始时初始化线程局部变量,然后从每个类中的每个方法访问它,并确保该变量将仅托管当前执行线程的跟踪信息。当它完成执行时,线程可以将其特定于线程的跟踪传递给负责维护所有跟踪的管理对象。

当您需要在每个线程的基础上存储变量实例时,使用 ThreadLocal 是有意义的。

于 2013-08-29T14:05:37.410 回答