美文网首页
ThreadLocal内存泄漏

ThreadLocal内存泄漏

作者: 拿拿guardian | 来源:发表于2020-09-27 15:51 被阅读0次

    ThreadLocal是为了解决对象不能被多线程共享访问的问题,通过ThreadLocal.set方法将对象实例保存在每个线程自己所拥有的threadLocalMap中,这样每个线程使用自己的对象实例,彼此不会影响达到隔离的作用,从而就解决了对象在被共享访问带来线程安全问题。

    内存泄漏问题

    每个线程都持有一个threadLocals实例,threadLocals的生命周期同线程个生命周期一样长。只要线程还存活,threadLocals实例就会被当前线程一直以强引用的方式持有。但是threadLocals的Key是以弱引用的方式被Entry所持有的,系统GC时,会被回收。所以会存在Entry的key为空但是value不为空的情况。Entry的key为空,导致Entry的value无法被访问到,但又无法被回收,所就内存泄漏了。

    优化

    在ThreadLocal的set和get方法中都有相应的处理。针对key为null的entry,有一定概率会清除其对应的无用的value。

    private void set(ThreadLocal<?> key, Object value) {
    
                // We don't use a fast path as with get() because it is at
                // least as common to use set() to create new entries as
                // it is to replace existing ones, in which case, a fast
                // path would fail more often than not.
    
                Entry[] tab = table;
                int len = tab.length;
                int i = key.threadLocalHashCode & (len-1);
    
                for (Entry e = tab[i];
                     e != null;
                     e = tab[i = nextIndex(i, len)]) {
                    ThreadLocal<?> k = e.get();
    
                    if (k == key) {
                        e.value = value; 
                        return;
                    }
    
                    if (k == null) {
                        replaceStaleEntry(key, value, i); // 这一步会对key=null,value!=null的场景中的value值做清空
    
                        return;
                    }
                }
    
                tab[i] = new Entry(key, value);
                int sz = ++size;
                if (!cleanSomeSlots(i, sz) && sz >= threshold)
                    rehash();
            }
    

    为什么使用弱引用

    如果使用强引用,在业务代码中执行threadLocalInstance==null操作,以清理掉threadLocal实例的目的,但是因为threadLocalMap的Entry强引用threadLocal,因此在gc的时候进行可达性分析,threadLocal依然可达,对threadLocal并不会进行垃圾回收,依然会内存泄漏。相对而言,使用弱引用虽然有存在内存泄漏的可能,但是代码上已经做了优化来保证内存泄漏的发生概率尽可能低。

    相关文章

      网友评论

          本文标题:ThreadLocal内存泄漏

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