- Pre talk
- ThreadLocal 是什么?解决了什么问题?
- ThreadLocal 源码分析及实现原理
- ThreadLocal 内存泄漏问题
- InheritableThreadLocal 的实现原理
Pre talk
线程封闭技术
访问共享可变数据时,通常需要使用同步,同步会产生性能问题,如何避免使用同步的方式来保证线程安全问题 – 不共享数据, 如何保证数据不共享呢? 如果仅仅是在单线程内访问数据,就不会存在数据共享的问题,也就不需要数据同步。 (线程封闭: Thread Confinement, 是实现线程安全最简单的方式之一)
当某个对象被封闭在一个线程中时, 这种用法将自动实现线程安全性,即使被封闭的对象本身不是线程安全的。
线程封闭常用的场景:JDBC 的 Connection 对象(非线程安全的连接池是没有意义的)
几种线程封闭技术
- Ad-hoc 线程封闭: 由程序来承担维护线程封闭性的职责(脆弱的)
- 栈封闭: 通过局部变量才能访问对象,局部变量的固有属性就是封闭在执行线程中(执行线程的栈中,因为变量是在栈中,栈是线程独立的)
- ThreadLocal: 是维持线程封闭性的规范的方法。ThreadLocal 能使线程中的某个值与保存值的对象关联起来。
ThreadLocal 是什么、解决了什么问题?
粗略的解释:ThreadLocal 类提供了线程本地的实例变量。这些变量与普通变量的区别在于:每个使用该变量的线程都会初始化一个独立的副本, ThreadLocal 修饰的实例,是一个典型的和线程相关联的私有的静态变量… (能力有限翻译不出来了)
ThreadLocal 对象通常用于防止对「可变的单实例变量」或「全局变量」进行共享,如 全局的数据库连接(Connection)。
ThreadLocal 通常称为:线程本地变量/线程本地存储。ThreadLocal 提供了 get 和 set 方法,为每一个使用该变量的线程存有一份独立的副本。( get 总是返回的当前执行线程在调用 set 时设置的最新值 )
一句话总结: ThreadLocal 为每个线程提供局部变量, 每个线程都可以通过 set() get() 对这个局部变量进行操作,但不会和其他线程的局部变量产生冲突, 进而实现线程的数据隔离,保证线程安全。
另外一定要注意:
- ThreadLocal 不是用来解决共享对象的多线程访问问题, 通过 ThreadLocal.set() 到线程中的对象是该线程自己使用的对应,其他线程是不需要访问的,也访问不到;(各个线程中访问的是不同的对象)
- ThreadLocal 使得各线程能够保持各自独立的对象, 并不是通过 ThreadLocal.set() 来实现的, 而是通过 每个线程中的 new 对象的操作来创建的对象,每个线程创建一个。
最常见的 ThreadLocal 使用场景是用来解决「数据库连接」、「Session 管理」等问题。
ThreadLocal 源码分析及实现原理
set()