ThreadLocal 的機制與內存泄漏

ThreadLocal筆記

kIEgyR.jpg

如上圖所示html

每一個Thread 都有一個map,裏面存着Entry<Key,value>,而key是實現了WeakReferenceThreadLocal,若是不是WeakReference,那麼可能Entry裏面的key和value在線程結束纔會進行GC,可是因爲是WeakReference,所以當Key被設置爲null時,key就會被 gc 回收.spa

可是因爲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;
}

中的code

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

expungeStaleEntry保證了key爲null的狀況下value也置爲nullhtm

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;
}

原文出處:https://www.cnblogs.com/Draymonder/p/10433516.htmlblog

相關文章
相關標籤/搜索