Home > Mobile >  why do we need to use ThreadLocal when we can create the variable inside the thread itself in java?
why do we need to use ThreadLocal when we can create the variable inside the thread itself in java?

Time:11-30

I know, we don't want to use global variables because then we will need to use synchronization which will affect the performance.

I also know that ThreadLocal is like a global variable, but every thread will have its version of it, and every thread can modify its version freely without affecting the other threads.

My Question is why don't we make every thread create its own version of that variable internally?

What is the benefit of using ThreadLocal that I can't achieve with any other mechanism?

Please provide a solid example if possible.

Note:- for any one that would suggest I should take a look at This question, the answers in that question don't answer my question because they don't say why I can't replace using ThreadLocal by creating the variable internally inside the thread.

CodePudding user response:

I think that is just a question of which side is managing the state. And as always , there is no right or wrong, just two ways of doing things.

with ThreadLocal you can write an implementation that would look like a program that is not concurrent (simple straightforward serial program). behind the scene any thread that will use it will be not be aware of how the implementation looks like.

here is example from my github for Trie like data structure

I used Thread Local to track for different threads - a pointer for the current node that I last read from, at any given time.

Now someone can use that Trie with a thread knowing that reading is thread safe.

I am not saying this is the optimal solution, or that it cannot be written better, just that it is a solution which is possible (which is very easy to write). In that specific solution I could make the data structure freeze and outsource the control as an iterator for a thread to manage and keep the track, but then again the client will have to manage the state. which way you prefer is up to the case, and up to you.

CodePudding user response:

Showing 2 options, thread local vs thread-save member, both work the same, while none need to know anything of the current-thread.

To use the ThreadLocal aproach, we could call from different threads:

new Bffer();
bffer.append1("Text");
bffer.getString();

The same can be done just using a thread-safe member of Bffer:

new Bffer();
bffer.append2("Text");
bffer.toString();
/**
 * Demonstrate String Buffer using ThreadLocal vs StringBuilder.
 */
public class Bffer {

    // Not thread safe object
    ThreadLocal<StringBuffer> tlBuf =
            ThreadLocal.withInitial(StringBuffer::new);

    // Thread safe object
    StringBuilder stringBuilder = new StringBuilder();

    public StringBuffer getTlBuf() {
        return tlBuf.get();
    }

    // Option 1 use ThreadLocal
    public String getString() {
        return stringBuilder.toString();
    }

    // Option 1 use ThreadLocal
    public void append1(final String s) {
        getTlBuf().append(s);
    }

    // Option 2 use ThreadLocal
    public String toString() {
        return getTlBuf().toString();
    }

    // Option 2 use thread safe variable
    public void append2(final String s) {
        stringBuilder.append(s);
    }

}

Note: There is never any need to have access to the running thread's implementation, as this is usually not recommended for several reasons. Today, if you need a Thread, you just instantiate a new Thread and give it the runnable to run:

new Thread(()->{/*implement routine*/});

CodePudding user response:

Consider this sketch of a program:

class Stuff {
   String x;
   ThreadLocal<String> y;
}

class MyThread extends Thread {
    Stuff stuff;
    MyThread(Stuff s) { stuff = s; }
    ...
}

Stuff stuff = new Stuff();

MyThread t1 = new MyThread(stuff);
t1.start();
MyThread t2 = new MyThread(stuff);
t2.start();

So we have two running threads sharing a common instance of Stuff. Within that Stuff, the variable 'x' is common to both threads, but each thread has its own instance of 'y'. That is the point of ThreadLocal.

Why would you want this? Well, it's difficult to see in this ginned-up example, but maybe Stuff needs both common state and per-thread state (in Stuff methods I have not shown). You could probably achieve that by splitting Stuff up into two classes, one you'd use per thread, and a common one pointed to by the per thread one. But this can be more convenient, especially when the ThreadLocal data is somehow necessary for the internal implementation of the common object.

ThreadLocal use is, I'd say, pretty uncommon. I'm sure I've written one once or twice in the past few years, but I can't remember when.

CodePudding user response:

I know, we don't want to use global variables...I also know that ThreadLocal is like a global variable...What is the benefit of using ThreadLocal...?

Three words: Reusing old code.

Suppose you have some amazing library that implements a magic algorithm. It took a lot of time and effort to create it, and you'd like to re-use it in your multi-threaded program. Only problem is, It was written back in the age of the dinosaurs, it's full of global variables, and it'll be a huge pain-in-the-you-know-what to ever create a thread-safe version of it, *UNLESS*...

...You turn all of those global variables into ThreadLocal variables.

If you do that, then each thread in your multi-threaded program can effectively use its own "copy" of the library without interfering with the others. Simple fix. You can probably trust an intern or a new hire fresh out of school to do the work.


It works better in C , by the way. In C , threadlocal is a language keyword—a storage attribute. All you have to do is add the keyword to the global variable declarations, and the job is done. You have to do a bit more work in Java because ThreadLocal is a class. You not only have to change all of the global Foobar declarations into ThreadLocal<Foobar>, but then you also have to explicitly create the ThreadLocal<Foobar> objects, and you have to hunt down all of the places where the variables are used, and replace them with foobar.get() and foobar.set() calls.

  • Related