美文网首页
线程之ThreadLocal

线程之ThreadLocal

作者: 呵呵_9e25 | 来源:发表于2019-04-15 18:27 被阅读0次

在谈线程的ThreadLocal之前需要了解一下java的引用

引用分类

1.强引用:我们平时通过new一个对象产生的对象名就是一个强引用,这是我们用的最广泛的引用

House house=new House();

强引用对象是即使内存再吃紧而且GC Roots可大,垃圾回收都不会回收这个对象

2.软引用:通过SoftReference进行对象指向

  House house=new House();
  SoftReference<House> reference=new SoftReference<House>(house);

软引用会把对象放到垃圾回收的队列中,在系统产生oom内存不足之前`就有可能去回收对象, 以保证系统的正常运行。

3.弱引用:比软引用更弱的引用,通过WeakReference进行对象指向

   House house=new House();
   WeakReference<House> reference=new WeakReference<House>(house);

弱应用的对象是在垃圾回收的时候更容易被回收,就是可以减少对强应用对象的挟持,减少内存泄漏

4.虚引用:最弱引用,通过PhantomReference进行对象指向

   House house=new House();
   PhantomReference<House> reference=new PhantomReference<House>(house);

虚引用只要垃圾回收就是回收该引用指向的对象,用的比较少,一般只用于获取对象回收时系统发出的通知

ThreadLocal

前面我们列举完了java的四大引用类型,然后我们现在就可以开始分析ThreadLocal了

ThreadLocal的作用

多线程之间进行数据共享,当多个线程同时操作一个统一对象的变量时,会产生数据错乱问题,其实就是同步问题,而我们的ThreadLocal正是为了解决这个问题。
ThreadLocal在每个线程中对该变量会创建一个副本,即每个线程内部都会有一个该变量,这样在同步的时候不同的线程操作的都是一个变量的副本,互相之间是不会有交集的。

实现原理

Thread->ThreadLocalMap->多个ThreadLocal变量
上面这个链状关系就是ThreadLocal实现多线程并发问题的核心原理。

我们简单解释一下
就是一个线程里会有一个容器ThreadLocalMap 容器的代码长这样

static class ThreadLocalMap {
       //每个线程都有一个存储变量副本的数组
        private ThreadLocal.ThreadLocalMap.Entry[] table;
      
        //以ThreadLocal的弱应用为键 值为变量副本
       static class Entry extends WeakReference<ThreadLocal<?>> {
            Object value;

            Entry(ThreadLocal<?> var1, Object var2) {
                super(var1);
                this.value = var2;
            }
        }
       
        //为线程添加变量副本
       private void set(ThreadLocal<?> var1, Object var2) {
            ...
            //给table数组元素赋值
            var3[var5] = new ThreadLocal.ThreadLocalMap.Entry(var1, var2);
            ...

        }
}
      

一个线程里可以有多个ThreadLocal对象,每个 ThreadLocal的都对应一个变量副本。
通过这个东西我们可以为每个线程创建一个变量副本,只要通过这个ThreadLocal来查找,最后是存储在这个ThreadLocalMap 里面。

然后重点是每个ThreadLocal都是一个弱引用,这样可以有效的避免内存泄漏。

问题

但是如果我们看过阿里的《码出搞笑 Java开发手册》的都应该知道,ThreadLocal有两个副作用,一个就是脏数据,另一个就是内存泄漏。

1.内存泄漏

那我们是不是打脸,是的,因为ThreadLocal在线程里面的声明是这样的

public class ThreadLocal<T> {
 
    public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> var0) {
        return new ThreadLocal.SuppliedThreadLocal(var0);
    }
}

返回的是一个static关键字声明的ThreadLocal,那即使gc也不能释放这个对象。

2.脏数据

就是在线程复用的时候如果ThreadLocal没有进行重新赋值,就是没有调用它的set()方法的话,你通过这个ThreadLocal查找回来的还是老数据,这就是脏数据产生的源头

解决方案:
两个问题的解决方案都是及时的调用remove()方法清理即可

相关文章

  • ThreadLocal

    ThreadLocal threadlocal 线程变量,每个线程都有单独的变量。用于线程之间的隔离。 Threa...

  • 揭秘ThreadLocal应用

    ThreadLocal ThreadLocal类用来提供线程内部的局部变量,不同的线程之间不会相互干扰,这种变量在...

  • Synchronized与Lock的区别

    其他:并发编程之ThreadLocal、Volatile、Synchronized、Atomic关键字Java并发...

  • ThreadLocal源码分析

    ThreadLocal作用 ThreadLocal用来存储线程的局部变量,不同线程之间的数据私有化,不能共享。在多...

  • 线程之ThreadLocal

    在谈线程的ThreadLocal之前需要了解一下java的引用 引用分类 1.强引用:我们平时通过new一个对象产...

  • 读读ThreadLocal

    前言 ThreadLocal给每个线程创建一个副本,方便线程存储本地数据。ThreadLocal不存在线程之间的数...

  • ThreadLocal的用法及原理

    一、用法 JDK 1.2的版本中就提供java.lang.ThreadLocal。ThreadLocal为解决多线...

  • 多线程之ThreadLocal

    Java中的ThreadLocal类可以让你创建的变量只被同一个线程进行读和写操作。 创建一个ThreadLoca...

  • 面试流程之 ThreadLocal

    面试官:“先问一个问题,如何在多线程的环境下保证数据不被其他线程修改?” 可以把这个数据用 ThreadLocal...

  • 多线程之ThreadLocal

    前言   前几天在京东的同学给我打了个电话,聊了下家常,技术宅的我多嘴问了最近有没有学啥? 他说最近有点忙,但抽空...

网友评论

      本文标题:线程之ThreadLocal

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