关于Threadlocal的源码分析和其与synchronized的选择

先简单介绍下Threadlocal,Threadlocal就是为每一个线程独立创建一个私有的本地变量,把原先的公共变量作用域范围缩小到了每个线程本身,这样在高并发的情况下就会更安全,这是和synchronized不同的地方,synchronized本质上操作的还是一个变量

我们先举个例子,来简单了解一下Threadlocal
在这里插入图片描述
在这里插入图片描述总共有三个线程对变量a进行累加,测试下结果
在这里插入图片描述
乍一看好像是正确的,并且执行顺序什么的都是正确的,我们来模拟一下在线程更多时候的情况
在这里插入图片描述
我们让T1线程睡一下,
在这里插入图片描述
发现线程运行顺序也乱了
下面我们使用Threadlocal来测试一下相同的功能
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
测试结果发现,他们的值居然都是5,究竟是为什么
我们发现他们的a值都是从num类中的threadlocal的get方法获取的,我们进去查看一下他的源代码
在这里插入图片描述
我们一步一步来解析
在这里插入图片描述
这一步是获取当前线程的引用,我们可以把它当做this
在这里插入图片描述
这一步把线程传递了进去,获取了一个ThreadLocalMap对象,这个ThreadLocalMap是做什么的?我们来看下他的getMap方法
在这里插入图片描述
我们发现,他其实就是为了返回当前引用线程的threadLocals,我们再来看下这个threadLocals
在这里插入图片描述
我们发现这个threadLocals其实就是一个ThreadLocalMap
我们再来看下面
在这里插入图片描述
ThreadLocalMap通过了自己内部的Entry来获取某个东西,如果Entry不为空,那么久返回Entry的value,我们看一下这个Entry
在这里插入图片描述
到了这一步我们应该就能猜到,ThreadLocalMap其实就是为了存储某些变量的,并且它是用Entry这种法师来进行存储的
我们在往下看,setInitialValue到底是什么
在这里插入图片描述
我们发现了,他其实就是为了存储这个传进来的对象,如果是第一次创建那么就保存进map,如果不是第一次创建就直接用,并且将T也就是当前线程的,value设置为了initialValue,我们再来看下这个initialValue方法
在这里插入图片描述
到这里我们大概就知道了该怎么去使用Threadlocal了,直接覆盖它的initialValue传递变量值就可以了
既然有get方法,那么应该也有set方法来设置这个值
我们来看下他的set方法
在这里插入图片描述
在这里插入图片描述
由于代码比较长我分了两次截图,这里我们就能看到,它是传入了ThreadLocal和Object来确定Entry的,其实就是一个map,键值对
到这里我们就基本清楚的它是怎么确定当前对象是哪一个和怎样传递参数的,并且也知道了它是如何为每一个线程创建自己的私有变量的,他就是将线程名和传递的参数值存到了map中,利用map独特的保存形式,即使你传递的参数是相同的,但是你的线程不同,所以你在map中存储的value值即使相同,key不同,存储的还是不一样的变量使用它会保证代码的安全性,他和synchronized的区别是什么呢
synchronized是锁机制,他会减少内存的损耗,在多线程的情况下会导致线程等待,性能会降低
ThreadLocal不一样,他会为每一个线程开辟自己的变量,但是会增加内存的损耗,在多线程的情况下也不会让每一个线程为了公共变量去等待,提高了效率

若有差错,还望指正,共勉

续加
关于threadlocal的关闭
在这里插入图片描述
我们可以看到它的关闭其实就是删除这个map中的键值对,所以在每个线程结束时remove就可以了

猜你喜欢

转载自blog.csdn.net/qq_43513205/article/details/88389571