美文网首页
理解ThreadLocal

理解ThreadLocal

作者: 陈二狗想吃肉 | 来源:发表于2020-10-30 00:44 被阅读0次

Spring容器中的单例Bean是否线程安全?

有状态对象(Stateful Bean) :就是有实例变量的对象,可以保存数据,是非线程安全的。每个用户有自己特有的一个实例,在用户的生存期内,bean保持了用户的信息,即“有状态”;一旦用户灭亡(调用结束或实例结束),bean的生命期也告结束。即每个用户最初都会得到一个初始的bean。

无状态对象(Stateless Bean):就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的。

对于单例Bean,所有线程都共享一个单例实例Bean,因此是存在资源的竞争。

如果单例Bean,是一个无状态Bean,也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。比如Spring mvc 的 Controller、Service、Dao等,这些Bean大多是无状态的,只关注于方法本身。

对于有状态的bean,Spring官方提供的bean,一般提供了通过ThreadLocal去解决线程安全的方法;


以下是对ThreadLocal的理解:



每个Thread类中有一个成员变量 threadlocals , 这个成员变量是一个 ThreadLocalMap的类型对象;

我们按住 Ctrl 键鼠标点击 ThreadLocalMap , 进入查看ThreadLocalMap 的底层实现

可以看到一个 Entry[] 数组:

可以看出,每个 Entry 键值对的键是 一个ThreadLocal 对象,值是一个 Object 对象。

这个ThreadLocalMap 类提供了set() 方来设置和添加键值对, 提供了get()方法来获取键值对,提供了remove()方法来删除键值对,看到这些方法,是不是觉得和 ThreadLocal 对象很像,因为ThreadLocal 类也提供了这个三个方法,分别用来存储对象值,获取对象值,以及移除对象值。

综上所述:

ThreadLocal 的set(), get(), remove()方法实际上在操作当前线程成员变量 threadlocals, 这个变量的类型是一个ThreadLocalMap, 所以当我们往ThreadLocal中添加值实际上是把值添加到了当前线程中,从 ThreadLocal 对象中取值实际上是从当前线程中取值,从ThreadLocal 对象中移除值实际上是从把这个值从当前线程中移除,所以一切操作都是在操作当前线程中的值,threadlocal在这里只是相当于一个索引作用;

-------------------------------------->>

ThreadLocal的内存泄漏问题

Entry 继承自WeakReference>,Entry的 key是ThreadLocal对象引用,这个引用是一个弱引用。当没指向 key 的强引用后,该key就会被垃圾收集器回收。

在ThreadLocalMap中,entry的key是弱引用,value仍然是一个强引用。

当某一条线程中的ThreadLocal使用完毕,没有强引用指向它的时候,这个key指向的对象就会被垃圾收集器回收,从而这个key就变成了null;所以entry就变成了(null, value), 而entry 和 value 都是强引用,并且只要entry还在,value就一直存在。所以如果我们不手动清理掉这些键为空的entry, 在线程执行完毕之前,这个entry就一直处于内存泄漏的状态。线程生命周期越长,内存泄漏的就越多。

解决办法:

hreadLocal提供了这个问题的解决方案。

(1)每次操作set、get、remove操作时,会相应调用 ThreadLocalMap 的三个方法,ThreadLocalMap的三个方法在每次被调用时 都会直接或间接调用一个expungeStaleEntry() 方法,这个方法会将key为null的 Entry 删除,从而避免内存泄漏

(2)如果一个线程运行周期比较长,而且将一个大对象放在LocalThreadMap后便不再调用set、get、remove方法仍然有可能key的弱引用被回收后,引用没有被回收,此时该仍然可能会导致内存泄漏。

所以需要程序员在使用ThreadLocal之后手动调用move删除;

既然弱引用会导致内存泄漏,那ThreadLocalMap为什么对ThreadLocal的引用要设置成弱引用?

为了尽快回收这个线程变量,因为这个线程变量可能使用场景不是特别多,所以希望使用完后能尽快被释放掉。因为线程拥有的资源越多,就越臃肿,线程切换的开销就越大,所以希望尽量降低线程拥有的资源量

相关文章

  • ThreadLocal

    理解ThreadLocal 理解ThreadLocal的关键在于理解 Thread, threadLocals, ...

  • ThreadLocal的使用事例

    列举几个使用ThreadLocal的事例,能更好的理解ThreadLocal。 1、运用ThreadLocal实现...

  • 14-ThreadLocal类详细剖析

    ThreadLocal类详细剖析 对ThreadLocal的理解 JDK中的源码是这样描述ThreadLocal的...

  • ThreadLocal 深度解析

    一.对ThreadLocal的理解二.深入解析ThreadLocal类三.ThreadLocal的应用场景 对Th...

  • ThreadLocal源码分析

    1.对ThreadLocal的理解 ThreadLocal是一个创建线程局部量的类。使用ThreadLocal创建...

  • ThreadLocal理解

    一、ThreadLocal的作用 ThreadLocal以线程作为作用域,针对每个线程维护他们自己的数据。每个线程...

  • ThreadLocal理解

    a

  • ThreadLocal理解

    MARK网址http://m.blog.csdn.net/article/details?id=24314381 ...

  • 理解ThreadLocal

    概述 ThreadLocal是一种线程封闭技术,用于隔离线程间的数据,从而避免使用同步控制。 一种避免使用同步的方...

  • ThreadLocal 理解

    Thread 变量 threadLocals 线程类Thread内部有一个名为threadLocals 的 Thr...

网友评论

      本文标题:理解ThreadLocal

      本文链接:https://www.haomeiwen.com/subject/pktrvktx.html