threadlocal的核心是通过隔离的方式来解决共享变量的安全性问题,这一方式能得以实现的基础是每个线程都有一个threadlocalmap,
我们可以通过threadlocalmap来存储,即以threadlocal为key的entry存储在threadlocal中,从而保证这个线程都会存有变量的副本,互不干扰,使用threadlocal基于以下几个事实:
1.每个thread都有一个threadlocalmap;
2.thread可以有多个threadlocal
3.threadlocalmap的key是threadlocal
4.threadlocal的核心方法有initValue,set,get,remove
5.使用threadlocal一般定义为static(防止线程过多时,创建的threadlocal过多,用static保证只有一个,当static修饰的变量不会随线程结束,鱼与熊掌不可兼得)
6.在调用set,get方法后要执行remove(1.在池化技术里存在线程复用,如果没有及时remove,可能会导致脏数据2.由于entry的value一直会被threalocal引用,且线程复用的情况下,容易内存泄漏)
7.threadlocal多用于连接池,spring
下面来从源码角度分析一下threadlocal的实现initValue,set,get,remove核心都是调用的threadlocalmap的set,get,remove方法
由以上代码可知threadlocal的核心是通过调用内部类threadlocalmap来实现数据的存储的,threadlocalmap有个内部类entry,entry的key弱引用了threadlocal(当没有其他强引用指向threadlocal时
,threadlocal在下次gc时一定会被回收),threadlocal的引用关系图如下:
Threadlocalmap的key如果发生了hash碰撞,会向后一直去查找对应的空位,而不是如hashmap一样以链表的方式去存储,代码如下:
threadlocal的测试:
可以发现如果不使用threadlocal会出现不同线程读到同一个数据
Spring事务同步管理器会把事务的一些公有属性用threadlocal定义,从而保证同一线程不同DAO拿到同一个connection,connection在resources里存储