The role of ThreadLocal

Is an internal thread storage class

  • Essentially, ThreadLocal trades space for time so that each thread has a copy of a variable that each thread can manipulate, completely circumventing the concurrency problem of multiple threads.

The basic use

  • code
public class ThreadLocalT {
    public static void main(String[] args) {
        ThreadLocal<String> threadLocal = new ThreadLocal<>();// The variable type maintained is String
        threadLocal.set("hello world");/ / the set value
        System.out.println(threadLocal.get());/ / get the value
        threadLocal.set("Kitty Guy");// The set value overrides the previous value
        System.out.println(threadLocal.get());// Get the latest set value}}Copy the code

Understand ThreadLocal in general

A constructor

Let’s look at the get method

  • The getMap method inside

  • The inside ThreadLocalMap

ThreadLocal’s static inner class, ThreadLocalMap, maintains an array table for each Thread. ThreadLocal determines an array subscript that corresponds to the location of the value store.

Let’s look at the set method

About the reference

  • There are four types of references in Java:
  1. Strong: Will not be garbage collected.
  2. Soft reference: When the memory is insufficient, it will be garbage collected.
  3. Weak reference: The next garbage collection will be collected. If you don’t have a strong reference to it.
  4. Phantom: Does not point to an object. When an object is reclaimed, it is notified for subsequent processing.

They differ in garbage collection timing, and all references except strong references are inheritedReference<T>

A memory leak

JVM memory in which ThreadLocal is present

The key is that the subscript (K) of the Entry array is a reference to ThreadLocal

Memory leaks are analyzed from two perspectives

Let’s assume that the reference to K is a strong reference

  • When the program runs to a point where it needs to destroy a ThreadLocal object, it first destroys the reference to ThreadLoacl on the stack.
  • Because the subscript K of the Entry array in the heap is a strong reference to ThreadLocal, this causes the stack reference to be destroyed, but the heap is not destroyed and cannot be destroyed. And that leads further.
  • The contents of the Entry array cannot be cleared. If the same Entry array is used multiple times, the above situation accumulates and the array fills up, resulting in a memory leak.
  • That is, K and V are stored in the array and cannot be cleaned up, so the array will fill up and the memory will leak.

Since strong references don’t work, use other references

The actual reference to K is a weak reference

A weak reference alone will not solve the memory leak

  • When the program runs to a point where it needs to destroy a ThreadLocal object, it first destroys the reference to ThreadLoacl on the stack.
  • The strong reference to ThreadLocal in the stack is destroyed. Since the subscript K of the Entry array in the heap is a weak reference to ThreadLocal, the ThreadLocal in the heap will be destroyed when the next garbage collection occurs because it is not strongly referenced. At this point
  • The case where K cannot be eliminated is solved. but
  • V is not deleted, resulting in a hollow V in the Entry but no corresponding array subscript. As a result, there will be many V’s in the array without corresponding K, and the number of V’s will continue to increase, leading to the overflow of the Entry array and memory leakage.

What if weak references don’t completely fix memory leaks?

Just do it at the code level

  • The JDK source code

When the get and set methods of ThreadLocal are called, the Value without K in the Entry array will be cleared because weak references will clear K in the Entry array, but not the Value. As long as the Value is cleared, the memory leak will be solved.

The following shape should be used in practical use of ThreadLocal to prevent memory leaks

public class ThreadLocalT {
    private static final ThreadLocal<String> threadLocal = new ThreadLocal<>();// The variable type maintained is String
        try{... . }finally {
        threadLocal.remove();// It is critical to prevent memory leaks}}Copy the code
  • Because weak references need to be removed on a strong reference basis before they can be garbage collected
  • Calling the remove method removes a strong reference from the stack. To ensure that memory leaks do not occur.

summary

  • ThreadLocal doesn’t really store variables; the Entry array in ThreadLocalMap does.
  • ThreadLocalMap is a member of the Thread class.
  • Calling ThreadLocal’s get, set, and remove methods clears the Entry array of values without a K.