java.lang.ThreadLocal - How each Thread has its own, independently initialized copy of the variable?

StackOverflow https://stackoverflow.com/questions/11360322

  •  19-06-2021
  •  | 
  •  

Question

The javadoc about the class java.lang.ThreadLocal is making me confused. They are saying that each thread that access a thread-local variable has its own, independently initialized copy of the variable. Here is an example (not a true life example) who proves that variable held in a thread-local variable could be shared by many threads:

package com.mohamad.test.threadlocal;

import java.util.List;

public class ThreadLocalExample {

    private static final ThreadLocal<List<Integer>> myThreadLocal = new ThreadLocal<List<Integer>>();

    public static List<Integer> get() {
        return (myThreadLocal.get());
    }

    public static void set(List<Integer> value) {
        myThreadLocal.set(value);
    }
}


package com.mohamad.test.threadlocal;

import java.util.ArrayList;
import java.util.List;


public class TestThreadLocal implements Runnable {

    private static List<Integer> MY_TEST_LIST = new ArrayList<Integer>(){
        /** The serialVersionUID */
        private static final long serialVersionUID = -2419885728976816054L;
        {add(1);}
    };


    /* (non-Javadoc)
     * @see java.lang.Runnable#run()
     */
    public void run() {
        ThreadLocalExample.set(MY_TEST_LIST);
        List<Integer> integers = ThreadLocalExample.get();
        integers.remove(0);
        System.out.println(Thread.currentThread().getName() + " finished successfully, The list's size is: "  + ThreadLocalExample.get().size() + "\n");
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        TestThreadLocal thread1 = new TestThreadLocal();
        Thread t1 = new Thread(thread1);
        t1.start();
        TestThreadLocal thread2 = new TestThreadLocal();
        Thread t2 = new Thread(thread2);
        t2.start();
    }
}

If we run this exemple, a java.lang.IndexOutOfBoundsException will be thrown because of the MY_TEST_LIST that is shared by thread1 and thread2. (And as we saw, when thread1 and thread2 called the set(MY_TEST_LIST) method of ThreadLocalExample, that called the set method of the ThreadLocal variable, it didn't create an independent local copy of the MY_TEST_LIST)

If somebody has already asked this question, please give the link to the answer because i did't find anything interesting while making a research on google.

Regards,

Was it helpful?

Solution

Everything is fine. Variable hold in ThreadLocal is local to the thread. In your case it is a reference that is local, not the list itself. Each thread has its own copy of the reference, but all these references point to the same location. In other words: each thread can keep a reference to a different List but in your case they all point to the same one.

If you want your example to work, each ThreadLocal should point to a different ArrayList (a copy):

myThreadLocal.set(new ArrayList<Integer>(value));

Having ThreadLocals all pointing to the same object doesn't make much sense as in this case you only need a single, globally available reference.

OTHER TIPS

You stored the same list reference inside two thread-local variables. That doesn't mean the ThreadLocal don't have a value per thread. Your test should start one thread which stores something into the thread-local, then start another thread that looks if the thread-local variable contains anything (and it won't).

That's exactly like if you had two Maps, and stored the same list in both maps. Obviously, if you modify the list stored in one map, the list stored in the other map will be modified, since it's the same list. But clearing one map doesn't clear the other map.

ThreadLocal doesn't enforce each thread to have a different reference, it allow each thread to potentially have its own copy depending on how you set it.

Just like each object having its own field, you can still set that field in every object to the same value, or you can set the values to be different.

It may be worth reading the source for the java.lang.Threads class to see how ThreadLocal is actually implemented.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top