首页 > 其他分享 >深入理解ThreadLocal底层原理

深入理解ThreadLocal底层原理

时间:2024-10-28 23:18:01浏览次数:7  
标签:map ThreadLocalMap value ThreadLocal 线程 Entry 原理 底层

ThreadLocal是线程私有的,各个线程之间是隔离的。可以想象一下每次线程创建的时候在堆上预先分配一个内存空间用于存储ThreadLocal的数据。

(1)当线程被创建时,线程都会有一个成员变量ThreadLocalMap。

//每个线程定义一个成员变量 ThreadLocalMap。
public class Thread implements Runnable {

    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;

}

(2)当ThreadLocal第一次调用Set(Value)存储的时候。ThreadlocalMap被实例化。

public class ThreadLocal<T> {
    /**
     * Sets the current thread's copy of this thread-local variable
     * to the specified value.  Most subclasses will have no need to
     * override this method, relying solely on the {@link #initialValue}
     * method to set the values of thread-locals.
     *
     * @param value the value to be stored in the current thread's copy of
     *        this thread-local.
     */
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            map.set(this, value);
        } else {
            // 第一次创建ThreadLocalMap对象。
            createMap(t, value);
        }
    }

    /**
     * Create the map associated with a ThreadLocal. Overridden in
     * InheritableThreadLocal.
     *
     * @param t the current thread
     * @param firstValue value for the initial entry of the map
     */
    void createMap(Thread t, T firstValue) {
        // 创建ThreadLocalMap对象,并且赋值给当前线程的成员变量。
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
}

(3)创建Entry[16]数组,封装Entry对象ThreadLocal作为key一一对应。

public class ThreadLocal<T> { 
  static class ThreadLocalMap {
         /**
         * The initial capacity -- MUST be a power of two.
         */
        private static final int INITIAL_CAPACITY = 16;
         /**
         * The table, resized as necessary.
         * table.length MUST always be a power of two.
         */
        private Entry[] table;

         /**
         * Construct a new map initially containing (firstKey, firstValue).
         * ThreadLocalMaps are constructed lazily, so we only create
         * one when we have at least one entry to put in it.
         */
        ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
            //创建16位Entry数组,并且初始化Entry[]的成员变量。
            table = new Entry[INITIAL_CAPACITY];
            int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
            //把ThreadLoacl对象最为key,封装到entry对象数组里面。
            table[i] = new Entry(firstKey, firstValue);
            size = 1;
            setThreshold(INITIAL_CAPACITY);
        }

        /**
         * The entries in this hash map extend WeakReference, using
         * its main ref field as the key (which is always a
         * ThreadLocal object).  Note that null keys (i.e. entry.get()
         * == null) mean that the key is no longer referenced, so the
         * entry can be expunged from table.  Such entries are referred to
         * as "stale entries" in the code that follows.
         */
        static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;
            // 一个Entry只能存放一个ThreadLocal的对象。
            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }
   }
}

(4)ThreadLocal<?>对象被弱引用对象WeakReference封装,随时可能会被GC回收。不管内存是否充足。

         思考一个问题?如果ThreadLocal对象被回收了,那么ThreadLocalMap里面的Enrty<K,V>数组元素Entry没有Key怎么办?Value值怎么获取?Entry<null,V> 越来越多是否会出现内存泄漏?

【Java并发编程】ThreadLocal(三):内存泄漏问题分析_threadlocalref-CSDN博客

标签:map,ThreadLocalMap,value,ThreadLocal,线程,Entry,原理,底层
From: https://blog.csdn.net/qq_22111417/article/details/143315273

相关文章

  • 【MySql进阶及常见方案】mysql索引底层原理和优化手段
    mysql索引底层原理和优化手段不管业务怎么发展,数据最终都要存储到数据库中,所以数据库是必不可少的一个环节。而随着业务逐渐壮大,并发越来越高,数据库很容易成为整个链路的短板。而调优的第一步,都是从sql语句、索引入手。先得保证单个数据库执行没问题,才会有更高层次的分库......
  • 深度解读GaussDB逻辑解码技术原理
    本文分享自华为云社区《【GaussTech技术专栏】GaussDB逻辑解码技术原理》,作者:GaussDB数据库。1.背景随着国内各大行业数字化改造步伐的加快,异构数据库数据同步的需求场景越来越多。异构数据库同步,即将不同类型、不同结构的数据库之间的数据进行同步处理,以确保数据在不同数据库......
  • 内网环回原理
    场景:当服务A和服务B都部署在同一个内网环境中,服务A试图通过服务B的公共IP地址进行请求。这种情况下,由于NAT环回的限制,可能会导致请求无法成功到达服务B。原理NAT设备通常维护两个个转换表,用于跟踪内网设备与公共IP地址之间的映射关系。分别是SNAT和DNAT,SNAT(......
  • 阿里面试:为什么要索引?什么是MySQL索引?底层结构是什么?
    文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录博客园版为您奉上珍贵的学习资源:免费赠送:《尼恩Java面试宝典》持续更新+史上最全+面试必备2000页+面试必备+大厂必备+涨薪必备免费赠送:《尼恩技术圣经+高并发系列PDF》,帮你实现技术自由,完成职业升级,薪......
  • 全面解释人工智能LLM模型的真实工作原理(三)
    前一篇:《全面解释人工智能LLM模型的真实工作原理(二)》序言:前面两节中,我们介绍了大语言模型的设计图和实现了一个能够生成自然语言的神经网络。这正是现代先进人工智能语言模型的雏形。不过,目前市面上的语言模型远比我们设计的这个复杂得多。那么,它们到底复杂在什么地方?本节将为你......
  • 我们来学mysql -- 用不上的索引(原理版)
    我们来学mysql--用不上的索引你行你上一张表一段有脑洞的阐述用不上的索引列你行你上轻松拿捏了两篇《使用索引》和《索引失效》知识点索引真是太香了,看的哈喇子都流出来了,必须给安排上在盲目的自信加持下,大刀阔斧的进行改革,为sql语句条件中的各个列创建索引一......
  • 强化学习的数学原理-04值迭代与策略迭代
    目录ValueiterationalgorithmPolicyiterationalgorithmTruncatedpolicyiterationalgorithmValueiterationalgorithm\[v_{k+1}=f(v_k)=\max_{\pi}\left(r_{\pi}+\gammaP_{\pi}v_k\right)\:,\:k\:=\:1,2,3,...\]算法可以被分为两步去做:\(Step1......
  • 改进的鲸鱼算法(IWOA)优化BP神经网络原理及Matlab代码复现
    目录0引言1数学模型2模型性能提升3Maltab代码3.1伪代码3.3IWOA-BP0引言为了缓解WOAQ易陷入局部最优和收敛精度低的问题,武泽权等人提出一种改进的鲸鱼优化算法(IWOA)。该算法通过准反向学习方法来初始化种群,提高种群的多样性;然后将线性收敛因子修改为非线性收......
  • 改进的鲸鱼算法(IWOA)优化支持向量机原理及Matlab代码复现
    目录0引言1数学模型2模型性能提升3Maltab代码3.1伪代码3.3IWOA-SVM/SVR0引言为了缓解WOAQ易陷入局部最优和收敛精度低的问题,武泽权等人提出一种改进的鲸鱼优化算法(IWOA)。该算法通过准反向学习方法来初始化种群,提高种群的多样性;然后将线性收敛因子修改为非......
  • epoll 或者kqueue 的原理是什么
    在处理大规模并发网络连接的领域中,epoll和kqueue代表了两种颠覆性的IO事件通知技术。它们被广泛应用于Linux和BSD系统中,以有效管理和优化网络通信过程。本文旨在深入探究epoll和kqueue的内部工作机制,揭示它们如何优于传统的select和poll方法,并分析其对现代网络编程带来的显著影响......