Volatile 关键字
使用场景
状态标志:Volatile常常用于多线程的状态标志,例如一个系统运行的标志位。一旦这个标志位改变,其他所有的线程都需要停止自己的工作。
双重检查锁定:在多线程环境下,volatile也常常和双重检查锁定一起使用,以实现线程安全的单例模式。
原理
volatile是Java提供的一种轻量级的同步机制,它主要有两个特性:
保证可见性:当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主内存,当有其他线程需要读取时,它会去内存中读取新值。
防止指令重排序:在Java内存模型中,为了提高处理器的效率,编译器和处理器常常会对指令进行重新排序,volatile可以防止指令重排序。
ThreadLocal
使用场景
每个线程需要有自己的单独的实例:例如在web开发中,每个请求都是一个独立的线程,而每个请求都需要有一个独立的数据库连接,这时候就可以用ThreadLocal来存储各自的数据库连接。
进行复杂的计算并且需要缓存部分结果:如果一个线程需要使用到预先计算的一些数据,而这些数据的计算很复杂,或者需要从远程服务器获取,这时候就可以考虑使用ThreadLocal来缓存这些数据。
原理
ThreadLocal为每个线程提供了一个独立的变量副本,每个线程都可以独立地改变自己的副本,而不会影响其他线程所对应的副本。ThreadLocal的实现中,内部有一个Map,用于存储每一个线程的副本。
ThreadLocal的key是弱引用,做这个设计主要是避免内存泄露。如果ThreadLocal没有外部强引用来引用它,那么在下一次垃圾回收时,这个ThreadLocal会被回收。这样,ThreadLocal在没有被外部强引用的情况下,其生命周期就与线程相同。
需要注意的是,虽然ThreadLocal能够防止共享资源的线程安全问题,但如果创建了ThreadLocal变量却不再使用,就可能导致内存泄漏,因为每个线程都会保留对其线程副本的引用,即使线程结束运行,如果不调用ThreadLocal的remove()方法,ThreadLocal的实例以及存储的数据对象都不会被垃圾回收。