面试必问:ThreadLocal 原理

什么是ThreadLocal

ThreadLocal 提供了线程内部的局部变量,当在多线程环境中使用 ThreadLocal 维护变量时,会为每个线程生成该变量的副本,每个线程只操作自己线程中的变量副本,不同线程间的数据相互隔离、互不影响,从而保证了线程的安全。

ThreadLocal 适用于无状态,副本变量独立后不影响业务逻辑的高并发场景,如果业务逻辑强依赖于变量副本,则不适合用 ThreadLocal 解决,需要另寻解决方案。

ThreadLocal 的数据结构

在 JDK8 中,每个线程 Thread 内部都维护了一个 ThreadLocalMap 的数据结构,ThreadLocalMap 中有一个由内部类 Entry 组成的 table 数组,Entry 的 key 就是线程的本地化对象 ThreadLocal,而 value 则存放了当前线程所操作的变量副本。每个 ThreadLocal 只能保存一个副本 value,并且各个线程的数据互不干扰,如果想要一个线程保存多个副本变量,就需要创建多个ThreadLocal。

一个 ThreadLocal 的值,会根据线程的不同,分散在 N 个线程中,所以获取 ThreadLocal 的 value,有两个步骤:

  • 第一步,根据线程获取 ThreadLocalMap
  • 第二步,根据自身从 ThreadLocalMap 中获取值,所以它的 this 就是 Map 的 Key

当执行 set() 方法时,其值是保存在当前线程的 ThreadLocal 变量副本中,当执行get() 方法中,是从当前线程的 ThreadLocal 的变量副本获取。所以对于不同的线程,每次获取副本值时,别的线程并不能获取到当前线程的副本值,形成了线程的隔离,互不干扰。

 

ThreadLocal 的核心方法

ThreadLocal 对外暴露的方法有4个:

  • initialValue()方法:返回为当前线程初始副本变量值。
  • get()方法:获取当前线程的副本变量值。
  • set()方法:保存当前线程的副本变量值。
  • remove()方法:移除当前前程的副本变量值

ThreadLocal 的哈希冲突的解决方法:线性探测

和 HashMap 不同,ThreadLocalMap 结构中没有 next 引用,也就是说 ThreadLocalMap 中解决哈希冲突的方式并非链表的方式,而是采用线性探测的方式,当发生哈希冲突时就将步长加1或减1,寻找下一个相邻的位置。如下图所示:

 

流程说明:

  • 根据 ThreadLocal 对象的 hash 值,定位到 table 中的位置 i;
  • 如果当前位置是 null,就初始化一个 Entry 对象放在位置 i 上;
  • 如果位置 i 已经有 Entry 对象了,如
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值