zoukankan      html  css  js  c++  java
  • ThreadLocal 的机制与内存泄漏

    ThreadLocal笔记

    kIEgyR.jpg

    如上图所示

    每个Thread 都有一个map,里面存着Entry<Key,value>,而key是实现了WeakReferenceThreadLocal,如果不是WeakReference,那么可能Entry里面的key和value在线程结束才会进行GC,但是由于是WeakReference,因此当Key被设置为null时,key就会被 gc 回收.

    但是由于value还在currentThread->Map->Entry->value中,因此导致了内存泄漏

    解决方法

    hreadLocalMap类的设计本身已经有了这一问题的解决方案,那就是在每次get()/set()/remove()ThreadLocalMap中的值的时候,会自动清理key为null的value。如此一来,value也能被回收了。

    private Entry getEntryAfterMiss(ThreadLocal<?> key, int i, Entry e) {
        Entry[] tab = table;
        int len = tab.length;
    
        while (e != null) {
            ThreadLocal<?> k = e.get();
            if (k == key)
                return e;
            if (k == null)
                expungeStaleEntry(i);
            else
                i = nextIndex(i, len);
            e = tab[i];
        }
        return null;
    }
    

    中的

    if (k == null)
        expungeStaleEntry(i);
    

    expungeStaleEntry保证了key为null的情况下value也置为null

    private int expungeStaleEntry(int staleSlot) {
        Entry[] tab = table;
        int len = tab.length;
    
        // expunge entry at staleSlot
        tab[staleSlot].value = null;
        tab[staleSlot] = null;
        size--;
    
        // Rehash until we encounter null
        Entry e;
        int i;
        for (i = nextIndex(staleSlot, len);
             (e = tab[i]) != null;
             i = nextIndex(i, len)) {
            ThreadLocal<?> k = e.get();
            if (k == null) {
                e.value = null;
                tab[i] = null;
                size--;
            } else {
                int h = k.threadLocalHashCode & (len - 1);
                if (h != i) {
                    tab[i] = null;
    
                    // Unlike Knuth 6.4 Algorithm R, we must scan until
                    // null because multiple entries could have been stale.
                    while (tab[h] != null)
                        h = nextIndex(h, len);
                    tab[h] = e;
                }
            }
        }
        return i;
    }
    
  • 相关阅读:
    C#中将结构类型数据存储到二进制文件中方法
    常用的20个在线工具类网站清单
    PyQt:开发小工具
    PyQt:使用QtDesigner设计界面
    经营策略
    Xmind 8 update 9 破解
    AI: 百度AI实战教学
    DRF:djangorestframework从入门到精通
    python:requests库发送参数+文件
    python:关于postman中生成的基于requests库的接口代码
  • 原文地址:https://www.cnblogs.com/Draymonder/p/10433516.html
Copyright © 2011-2022 走看看