当前位置:网站首页>ThreadLocal 总结(未完待续)
ThreadLocal 总结(未完待续)
2022-07-25 22:12:00 【斯沃福德】
ThreadLocal
1. Java内存模型:
- Java所有变量都存储在主内存中
- 每个线程都有自己独立的工作内存,里面保存该线程的使用到的变量副本(该副本就是主内存中该变量的一份拷贝)
- 线程对共享变量的所有操作都必须在自己的工作内存中进行,不能直接在主内存中读写,线程修改完变量之后要刷新到主内存中;
- 不同线程之间无法直接访问其他线程工作内存中的变量,线程间变量值的传递需要通过主内存来完成。
线程1对共享变量的修改,要想被线程2及时看到,必须经过如下2个过程:
①把工作内存1中更新过的共享变量刷新到主内存中
②将主内存中最新的共享变量的值更新到工作内存2中
2. 背景
多个线程对一个变量进行写入的时候容易产生线程安全问题,一般使用者在访问共享变量的时候需要进行额外的同步措施才能保证线程安全性;
ThreadLocal是除了加锁这种同步方式之外的一种保证一种规避多线程访问出现线程不安全的方法;
当我们在创建一个变量后,如果每个线程对其进行访问的时候访问的都是线程自己的变量,这样就不会有线程安全问题了。(以数据隔离的方式来保证线程安全)
3. 概述
ThreadLocal为每一个线程都提供一个专属的变量副本,使每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突;
如果你创建了⼀个 ThreadLocal 变量,那么访问这个变量的每个线程都会有这个变量的本地副本;
可以使⽤ get() 和 set() ⽅法来获取默认值或将其值更改为当前线程所存的副本的值,从而避免了线程安全问题;
例:
ThreadLocal的数据是隔离的,每个线程都能拿到变量的副本,线程2 拿到的还是null !
4. 结构
JDK8之前: key是Thread,由Threadlocal来维护ThreadlocalMap 
JDK8改变结构的好处:
1.Thread作为Key,则线程很多时Entry会很多,而ThreadLocal作为Key,Entry数量会减少很多;key少了就能尽量避免哈希冲突
2.当Thread销毁时,ThreadLocalMap也会随之销毁,减少内存开销;而早期ThreadLocalMap由ThreadLocal维护,线程结束并不会销毁ThreadLocalMap;
JDK8中结构: key是threadLocal对象,由Thread线程来维护threadLocalMap

结构说明:
每个Thread维护一个ThreadLocalMap,
Key是Threadlocal对象,value就是Threadlocal的set方法存的值(变量副本);
对于不同的线程,有着各自不同的ThreadLocalMap,所以就能使数据副本的隔离;
5. set() 、get()、remove()方法源码
5.1 set()
1.先获取当前线程对象;
2.获取线程对象的threadLocals属性,也就是threadLocalMap;
3.如果map存在就将当前threadLocal对象作为key,传入的值作为value传入map; 如果map为空就会创建一个map



5.2 get()
1.获取当前Thread线程对象;
2.获取线程的threadLocals即threadLocalMap;
3.当map存在,以当前的threadLocal对象为key,调用map.getEntry方法拿到Entry实体,若Entry实体不为空则取出Entry试题中的value;
4.①如果map不存在 或 ②没有与当前threadLocal对象关联的Entry调用setInitiavalue()设置初始化方法:
判断map,如果为空则创造map;
如果map不为空则把当前ThreadLocal对象作为key,和value存入map


5.3 remove()
1.获取当前线程对象;
2.获取线程的threadLocals即threadLocalMap;
3.如果map不为空就溢出当前threadLocal对象关联的Entry
6. 内存泄露问题
ThreadLocalMap 中使⽤的 key 为 ThreadLocal 的弱引用,⽽ value 是强引用。所以,如果
ThreadLocal 没有被外部强引⽤的情况下,在垃圾回收的时候,key 会被清理掉,⽽ value 不会被清理掉;
这样⼀来, ThreadLocalMap 中就会出现key为null的Entry,假如我们不做任何措施的话,value 永远⽆法被GC 回收,这个时候就可能会产⽣内存泄露。
ThreadLocalMap实现中已经考虑了这种情况,在调⽤ set() 、 get() 、 remove() 方法的时候,会清理掉 key 为 null 的记录。
使用完ThreadLocal 方法后 最好手动调用 remove() 方法;
边栏推荐
- Virtual memory and disk
- SQL中in的用法 DQL 查询
- Redis基础2(笔记)
- jenkins+SVN配置
- JSP初识
- C language: random generated number + selective sorting
- Output Yang Hui triangle with two-dimensional array
- 测试工作不受重视,你换位思考了吗?
- mysql: error while loading shared libraries: libncurses.so. 5: cannot open shared object file: No suc
- What is redis? Briefly describe its advantages and disadvantages
猜你喜欢
![[go basics 02] the first procedure](/img/af/f32762a828f384bf6aa063ebf959aa.png)
[go basics 02] the first procedure

2 lines of code to generate a solid desktop background

如何实现一个App应用程序,限制用户时间使用?

【C语法】void*浅说

『Skywalking』. Net core fast access distributed link tracking platform

【汇编语言01】基础知识

Wet- a good choice for people with English difficulties - console translation

How to implement an app application to limit users' time use?

6-17 vulnerability exploitation - deserialization remote command execution vulnerability

H5 lucky scratch lottery free official account + direct operation
随机推荐
[assembly language 01] basic knowledge
c sqlite ... ...
QML module not found
JSP novice
Recursive case -c
internship:普通常用的工具类编写
El expression improves JSP
[go basics 02] the first procedure
2年功能测试,却感觉自己什么都不会,2022我该何去何从?
SQL中in的用法 DQL 查询
Fill the whole square with the float property
jsp九大内置对象
win10搭建flutter环境踩坑日记
[dinner talk] those things that seem to be for the sake of the company but are actually incomprehensible (2: soft quality "eye edge" during interview)
Don't vote, software testing posts are saturated
6-18 vulnerability exploitation - backdoor connection
Minor GC 和 Full GC 有什么不同呢?
Synchronized and volatile
Wechat card issuing applet source code - automatic card issuing applet source code - with flow main function
SQL basic statement DQL select and extract DML insert delete