Spring学习记录6——ThreadLocal简介

Spring通过各种模板类降低了开发者使用各种数据持久化技术的难度。这些模板类是线程安全的,所以 多个DAO可以复用同一个模板实例而不会发生冲突。在使用模板类访问底层数据时,模板类需要绑定数据连接或者会话的资源,然而这些资源本身是非线程安全的,无法在同时刻被多个线程共享。虽然模板类是通过资源池获取数据连接或会话,但资源池本身解决的是数据连接或会话的缓存问题,并非数据连接或会话的线程安全问题。

按照经验,如果某个对象是非线程安全的,在多线程环境下对对象的访问必须采用synchronized进行线程同步。蛋模板类并没有采取线程同步机制,因为线程同步会降低并发性,影响性能。Spring在处理这个问题时使用的就是ThreadLocal。ThreadLocal在Spring中发挥重要作用,在管理request作用域的Bean、事务管理、任务调度、AOP等模块中都有涉及。

ThreadLocal是什么

ThreadLocal不是一个线程,而是保存线程本地化对象的容器。当运行于多线程环境的某个对象使用ThreadLoacl维护变量时,ThreadLocal为每个使用该变量的线程分配一个独立的变量副本。所以每个线程都可以独立地改变自己的副本,而不会影响其他线程所对应的副本。从线程的角度看,这个变量就像线程专有的本地变量,这也是“Local”所要表达的意思。

ThreadLocal实现的思路:在ThreadLocal类中有一个Map,用于储存每个线程的变量副本,Map中元素的键为线程对象,值为对应线程的变量副本。

ThreadLocal与Thread同步机制的比较

ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。

在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序缜密的分析什么时候对变量进行读/写,什么时候释放锁等问题,设计难度相对较大。

而ThreadLocal从另一个角度解决多线程并发访问。ThreadLocal为每个线程提供了一个独立的变量副本,从而隔离了多个线程对访问数据的冲突。因为每个线程都拥有自己的变量副本,所以就没必要对该变量进行同步。

总之,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,访问是按顺序串联进行的,对象是共享的;而ThreadLocal采用“以空间换时间”的方式”,访问是多线程并行,对象是独享的。前者仅提供一份变量,让不同线程排队访问,而后者为每个线程都提供了一份变量,因此可以同时访问而互不影响。

相关推荐