如果我使用threadlocal变量,那么每个线程都会获得变量的本地副本。我的第一个问题是,如果每个线程都变异变量,那么变异值是否只会保留在本地副本中?或者在某些时候它会尝试更新'全局变量',我们会遇到并发问题?
我的另一个问题是:如果我在方法中声明一个变量,那么在自己的堆栈中执行该方法的每个线程都将获得自己的副本。那么声明一个方法级变量和使它成为threadlocal一样吗?
答案 0 :(得分:3)
第一个问题:每个线程都更新了threadlocal变量的副本,线程之间没有共享全局状态。
第二个问题:如果声明局部变量,它的行为与threadlocal相似 - 每个线程都有自己的副本,但是你没有全局访问它,例如在另一种方法中 - 当threadlocal有用时。
答案 1 :(得分:1)
查看ThreadLocal<T>
对象的最简单方法是Map<Thread, T>
,其中ThreadLocal#get()
调用将通过调用基础{Map#get(Thread.currentThread())
来查找正确的值1}}。请注意,这不是实际的实现,而是查看它的最简单方法。
Map
个变量仅作为一个实际可由多个线程同时访问的成员使用。方法中变量的局部声明只是本地声明,因此其他线程无法访问。我不会说它们是“相同的”,但它们都是线程安全的。
在多线程环境中,典型用法是单个对象的实例成员变量,或类的静态成员变量。
通常,您会看到它们用于在servlet环境中传递请求上下文信息。
答案 2 :(得分:1)
如果我使用threadlocal变量,那么每个线程都会获得一个本地副本 变量
我认为关于术语变量的本地副本存在一些混淆。没有副本。每个线程都有自己的变量;这些是彼此独立的。但是,它并不意味着它们不能保持对共享对象的引用。因此,仅仅使用threadlocal变量并不能避免出现并发问题。
关于你的第二个问题:不。局部变量和线程局部变量是不同的。局部变量在定义它们的块之外是不可访问的。因此,例如,两次调用相同的方法将导致每次都有不同的值。另一方面,只要线程存在,threadlocal变量就会保留它们的值。
基本上,threadlocal变量是一个单个线程的“静态”变量。
答案 3 :(得分:0)
ThreadLocal变量的一个重点是全局访问。它可以从thread.inside中的任何方法访问任何调用该线程上下文的方法。
如果要为类的所有实例维护变量的单个实例,则将使用静态类成员变量来执行此操作。如果要基于每个线程维护变量的实例,则将使用线程局部变量。 ThreadLocal变量与普通变量不同,因为每个线程都有自己独立初始化的变量实例,它通过get()或set()方法访问。
假设您正在开发一个多线程代码跟踪器,其目标是通过代码唯一标识每个线程的路径。挑战在于您需要跨多个线程协调多个类中的多个方法。没有ThreadLocal,这将是一个复杂的问题。当一个线程开始执行时,它需要生成一个唯一的令牌以在跟踪器中识别它,然后将该唯一令牌传递给跟踪中的每个方法。
使用ThreadLocal,事情变得更简单。该线程在执行开始时初始化线程局部变量,然后从每个类中的每个方法访问它,并确保该变量仅托管当前正在执行的线程的跟踪信息。当它完成执行时,线程可以将其特定于线程的跟踪传递给负责维护所有跟踪的管理对象。
当您需要在每个线程的基础上存储变量实例时,使用ThreadLocal是有意义的。