This chapter focuses on the local thread variable ThreadLocal
What is a ThreadLocal
In what we know as concurrency, there is no guarantee of thread-safety when multiple threads access a shared resource. Ordinary users need to perform additional synchronization operations to access shared variables. ThreadLocal is a guaranteed way to avoid thread insecurity in addition to locking. When we create a variable, if each thread accesses its own variable, there is no thread insecurity. A shared copy of a variable is stored within the thread itself. This way, changes to variables do not affect other threads.
How ThreadLocal works
- Each thread has a threadLocalMap
- A ThreadLocalMap is like a Map itself, with key-value pairs in the form of key values, which are references to threadLocal. Value is what’s stored.
The set of source code
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if(map ! = null) map.set(this, value);
else createMap(t, value); } Copy the code
The set method is used to store the value we want to store. The first step is to get a reference to the current thread. The ThreadLocalMap is obtained based on the getMap method and the current thread reference, and the value is stored with the current ThreadLoacl as the key.
Get the source code
public T get() {
// Get the current thread Thread t = Thread.currentThread();
A ThreadLocalMap object is available in each thread ThreadLocalMap map = getMap(t);
if(map ! = null) {// Get the Entry object in ThreadLocalMap and get the Value ThreadLocalMap.Entry e = map.getEntry(this); if(e ! = null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } ThreadLocalMap is created if it has not been created before return setInitialValue(); } Copy the code
GetMap () and a reference to the current thread to get ThreadLocalMap. ThreadLocalMap is similar to a HashMap in that you can get an Entry object based on getEntry (ThreadLocal, also known as this) and a stored value via entry. value
What if you need multiple thread variables in one thread?
As described above, if you need multiple thread variables, you need to define multiple ThreadLocal to use.
ThreadLocal must remove()
ThreadLocal can cause memory leaks
On the left is the reference stack, which contains a reference to ThreadLocal and a reference to a thread, and on the right is our heap, which contains instances of objects.
Thread Ref → Current Thread → ThreadLocalMap → Entry → Value → Value instance
static class Entry extends WeakReference<ThreadLocal<? > > { /** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<? > k, Object v) { super(k); value = v; } } Copy the code
The internal of ThreadLocalMap is actually an array of entries. As described in the above code, the reference k of the current ThreadLocal is passed to the constructor of WeakReference, so the key in ThreadLocalMap is the WeakReference of ThreadLocal. When a thread calls ThreadLocal’s set method to set a variable, the current thread’s ThreadLocalMap stores a record whose key is a weak reference to ThreadLocal, and whose value is the set value.
If the ThreadLocal is not referenced elsewhere,gc will reclaim the weakly referenced key, but the value is not a weak reference. In this case, an entry with a null key and a non-null value will appear. Causing memory leaks
Remove the source code
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if(m ! = null) m.remove(this);
}
Copy the code
Remove removes the value of the key. Then GC can reclaim it.
This article is formatted using MDNICE