ThreadLocal 原理探究

ThreadLocal 的作用:

This class provides thread-local variables. 提供了线程级别的本地变量。

ThreadLocal的原理:

  1. 每一个线程Thread内部维护了两个package private级别的变量:
    • ThreadLocal.ThreadLocalMap threadLocals
    • ThreadLocal.ThreadLocalMap inheritableThreadLocals
  2. 每一个 ThreadLocal 对象有一个创建时生成唯一的 Id称为:threadLocalHashCode,访问一个 ThreadLocal 变量的值,就是用threadLocalHashCode去 本线程 的 ThreadLocalMap 中查找对应的值。

    private Entry getEntry(ThreadLocal<?> key) {
     int i = key.threadLocalHashCode 
     & (table.length - 1);
     Entry e = table[i];
     if (e != null && e.get() == key)
         return e;
     else
         return getEntryAfterMiss(key, i, e);
    }
  3. ThreadLocalMap 为一个静态内部类,包含了一个Entity数组(Entry[] table)来保持ThreadLocal的线程变量;

ThreadLocalMap的原理

  1. ThreadLocalMap是一个Hash Map,采用的是开放地址法而不是链表的方式解决冲突。
  2. Entry 是 WeakReference 的子类,这样不再被使用的 ThreadLocal 可以被检查出来并清除掉。
  3. 线程隔离的秘密,就在于ThreadLocalMap这个类。ThreadLocalMap是ThreadLocal类的一个静态内部类,它实现了键值对的设置和获取(对比Map对象来理解),每个线程中都有一个独立的ThreadLocalMap副本,它所存储的值,只能被当前线程读取和修改。ThreadLocal类通过操作每一个线程特有的ThreadLocalMap副本,从而实现了变量访问在不同线程中的隔离。因为每个线程的变量都是自己特有的,完全不会有并发错误。还有一点就是,ThreadLocalMap存储的键值对中的键是this对象指向的ThreadLocal对象,而值就是你所设置的对象了。

    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
       void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

神奇的 0x61c88647

待补充;

使用陷阱:

  1. ThreadLocal和线程池同时使用出现变量污染;
    在使用线程池的过程中,由于线程是不断的回收和利用故ThreadLocal在服务器中也是被反复利用的,在使用中如果不进行清查操作,很容易导致变量污染。

问题:

❓疑惑1:既然ThreadLocal只维护一个值,每一个Thread中都存储的是一个副本,为什么ThreadLocalMap需要时一个数组而不是object呢?

原因:如果我们期望在一个Thread中存储多个ThreadLocal变量怎么办呢?不可能改造Thread,新增一个Object对象吧,所以为了更方便的在同一个Thread中加入多个ThreadLocal变量,才引入了数组结构,不同的ThreadLocal对象作为不同键,所以在线程的ThreadLocalMap对象中设置不同的值。

❓疑惑2:ThreadLocalMap为什么采用开放地址的方法,而不采用链表来防止hash冲突?

扩展阅读:
http://qifuguang.me/2015/09/02/[Java%E5%B9%B6%E5%8F%91%E5%8C%85%E5%AD%A6%E4%B9%A0%E4%B8%83]%E8%A7%A3%E5%AF%86ThreadLocal/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值