1

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.

Ahmed Eid
  • 61
  • 6
  • 2
    You *can* create your own thread implementation and keep track of a variable there. This also *requires* you to write your own thread implementation, you have to cast 'current thread' to your type, and that's all. Usually, when you use ThreadLocal, you don't control the thread, such that you don't implement or even know what thread implementation is there at runtime. For common libraries the case is that they have to work on any thread using them. Think of containers, your code runs on a given container's thread. – MJG Nov 30 '22 at 11:54
  • @MJG thanks MJG for you comment, but I didn't completely get you point. Can you elaborate with an answer and provide a code example. – Ahmed Eid Nov 30 '22 at 12:04

5 Answers5

0

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.

  • Thanks Aviad Shiber for your answer but you still didn't my question, why didn't we create the variable inside the thread instead of using ThreadLocal? – Ahmed Eid Nov 30 '22 at 13:19
  • What will we lose if we didn't use ThreadLocal? – Ahmed Eid Nov 30 '22 at 13:19
  • @Ahmed Eid you mean why it is not just a simple pointer inside the Trie class? that would make the implementation not a thread safe.. two (or more) threads will be able to access the pointer and update the pointer and causing a data corruption, or stale data or any other concurrent issue. with Thread local you just know that each thread does not share a state and it is managed for you by the Trie (not outside by the client thread). And then is just a question of who keep track of the last node, the client(the thread) or the Trie. – Aviad Shiber Nov 30 '22 at 13:32
0

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*/});
MJG
  • 355
  • 1
  • 9
  • Thanks MJG for your answer, but you still didn't answer my question, Why don't I create the variable internally inside the thread instead of using ThreadLocal? – Ahmed Eid Nov 30 '22 at 12:50
  • What will I lose if I don't use ThreadLocal? – Ahmed Eid Nov 30 '22 at 12:50
  • Perhaps some misunderstanding here. ThreadLocal is returning a different object *every time* when accessed on a different thread. A private member of the Thread is *the same* when accessed on different threads. Even your thread itself runs inside another thread. So it is a more relevant question, *what is* ThreadLocal, before asking what could I do instead? – MJG Nov 30 '22 at 14:08
0

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.

0

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.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57
0

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

You could. If these were long running threads then creating an instance of the object in question so it could be used by the thread would be fine.

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

The common use case is a library which is using some expensive resource. Multiple threads call into this library but you don't want to create the expensive resource each time – SimpleDateFormat is one example since it is not reentrant. You want to convert sys-time-millis into a string for logging purposes inside of the library but you don't want to have to do the date format parsing for each logging call so you parse it once and store it in a ThreadLocal.

Another example is when you are using a thread-pool to process a large number of lines from a file. You create 100,000s of Runnable jobs and submit them to the thread-pool with 4 threads. Each job can use a ThreadLocal manage the line processing object which is expensive to create so only 4 of these are created, each one of them stored in each of the thread's ThreadLocal storage.

One of the problems with ThreadLocal variables is that it can be hard to free up the resources from them. People use object pools for the same purpose but at the end you can clean up the objects in the pool as opposed to those objects stored in the ThreadLocal.

Gray
  • 115,027
  • 24
  • 293
  • 354