Win a copy of Re-engineering Legacy Software this week in the Refactoring forum
or Docker in Action in the Cloud/Virtualization forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

ThreadLocal variable and static TL variable

 
Tejas Aryan
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have gone through many articles and tried to understand the ThreadLocal variable and what happens when ThreadLocal variable is declared as static. As I understand, thread local variables are local to each threads. But I am not able to understand how a static thread local variable would behave in such context.

Please put in your understanding to help me understand better.
 
Henry Wong
author
Marshal
Pie
Posts: 20902
76
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There is no such a distinction as a "static TL variable". A thread local instance can be referenced by an instance variable or a static variable; Or even both at the same time. The difference in behavior is the same difference in behavior applied to any other object.

Henry
 
Jelle Klap
Bartender
Posts: 1951
7
Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You seem to understand what a ThreadLocal variable is. From the from the JavaDoc:

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread.


What do you know about static variables and instance variables, how do they differ? Given that, why would the JavaDoc state that "ThreadLocal instances are typically private static"?

Edit: Ugh ninja'ed by Henry ;)
 
Henry Wong
author
Marshal
Pie
Posts: 20902
76
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jelle Klap wrote:
Edit: Ugh ninja'ed by Henry ;)



Sorry...

Amazing timing though -- 20 hours without an answer, then 2 responses within 5 minutes.

Henry
 
Dmitry Zhuravlev
Ranch Hand
Posts: 93
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Actually this old topic looks interesting for me.

As we know static variable has only one instance - instance bound with the class object instance.

But static ThreadLocal variable can have many instances per class! Of course, actually these instances are hidden inside one reference to ThreadLocal, for example:


- this line of code will produce one myThreadLocal reference as usual for static variables, but many Integer instances for each of the threads accessing it.. So actually this looks like a special static variable that can have many instances per class.. Probably this fact surprised the topic starter. Concurrency Gurus, please correct me if I am wrong.

(Yes, I see the dates. Just some personal interest for ThreadLocals)
 
Nitesh Kant
Bartender
Posts: 1638
IntelliJ IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dmitry Zhuravlev wrote:
So actually this looks like a special static variable that can have many instances per class..


Not per class but per thread. You can think of a TL as a Map where the key is the thread ID and the value is the value of the variable per thread.
So, conceptually the variable contains multiple values (just like any other collection variable), whether the multiple values have affinity with a thread or not is not something that is important in reference to a static or non-static TL.
 
assert assertion
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think a static TL will have exactly the same behavior as a member TL variable. However a member TL variable cannot be accessed from a static method. Static TL variables are to support static methods .
 
ramesh vanka
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
ThreadLocal instance associated Thread,
run(){
ThreadLocal a = new ThreadLocal();
a.set(Thread.currentThread().getName());
}
Two threads t1,t2 threads are running.
T1 Scenario:
ThreadLocal internally maintain map. In map(KEY, VALUE) ,
KEY = THREAD IDENTIFIER,Based thread hashcode and some logic, it will generate the Thread Identifier
Value= a.set(Thread.currentThread().getName());

so when ever T1 issues t1.get(), first it will check internal map, In the map it have thread identifier it will give the value.

T1 Scenario:
Same like that.

Hope It will clear the doubts.

 
Henry Wong
author
Marshal
Pie
Posts: 20902
76
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
ramesh vanka wrote:ThreadLocal instance associated Thread,
run(){
ThreadLocal a = new ThreadLocal();
a.set(Thread.currentThread().getName());
}
Two threads t1,t2 threads are running.
T1 Scenario:
ThreadLocal internally maintain map. In map(KEY, VALUE) ,
KEY = THREAD IDENTIFIER,Based thread hashcode and some logic, it will generate the Thread Identifier
Value= a.set(Thread.currentThread().getName());

so when ever T1 issues t1.get(), first it will check internal map, In the map it have thread identifier it will give the value.

T1 Scenario:
Same like that.

Hope It will clear the doubts.




Using the analogy that the ThreadLocal class maintaining a map, with the calling thread as a key is actually a good way to remember what it does. However, this is not how the implementation works -- the ThreadLocal class actually stores the value in the Thread object, so while the threadlocal class will use the thread object, but there is no reason to hash the thread object.

Henry
 
Eduardo Moranchel
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The way i understand it:

A thread local is a class.
It has a value per thread.
It is a key/value store where the key is the Thread ID and the value is whatever we put inside
Wait. is it... like a map?
maybe. lets think it this way.
All threads have a unique ID, that can be the key of the map.
And we store a value inside.
So we can say a ThreadLocal can be actually a Map<ThreadId, ValueType> variable.
but handling maps and stuff is bad and boring so why not disguise it with ThreadLocal<ValueType>
ok now then how do we get the id?
Thread.getCurrentThread().getId ? something like that exists actually.
So there you have it. how ThreadLocals work.

Being static is just in case you want to access it from different objects regardless of where they are (a convenient way of passing the variable around) but is in no way mandatory.
 
Henry Wong
author
Marshal
Pie
Posts: 20902
76
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Eduardo Moranchel wrote:The way i understand it:

A thread local is a class.
It has a value per thread.
It is a key/value store where the key is the Thread ID and the value is whatever we put inside
Wait. is it... like a map?
maybe. lets think it this way.
All threads have a unique ID, that can be the key of the map.
And we store a value inside.
So we can say a ThreadLocal can be actually a Map<ThreadId, ValueType> variable.
but handling maps and stuff is bad and boring so why not disguise it with ThreadLocal<ValueType>
ok now then how do we get the id?
Thread.getCurrentThread().getId ? something like that exists actually.
So there you have it. how ThreadLocals work.


Actually, that is not how threadlocals work -- it is just easier to think of it as a map that routes values based on the thread id as the key.... meaning you can envision it that way. It is not a disguised map.

As already mentioned, the ThreadLocal class actually stores the values internally in the Thread object that represents the thread. The data is actually not stored in the ThreadLocal object.

Henry
 
tushar pagar
Greenhorn
Posts: 1
Eclipse IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I agree with Henry.
If ThreadLocal was a map, then it would be difficult accessing it concurrently. This will have a performance hit as all threads who are trying to set ThreadLocal will have to synchronize over the threadlocal object.
 
ramesh vanka
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

I am pasting here inside ThreadLocal snippet:

public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}

public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}

ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}

void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}


run(){
ThreadLocal a = new ThreadLocal();
a.set(Thread.currentThread().getName());
}
Two threads t1,t2 threads are running.
T1 Scenario:
ThreadLocal internally maintain map. In map(KEY, VALUE) ,

My Comments:
When the user called a.set(Thread.currentThread().getName()) Initially,
1) if it will check corresponding thread's any threadlocalmap is there or not
2) For 1st time corresponding threadlocalmap is null, so that it will call createMap(Thread t, T firstValue) , here you are creating new Threadlocalmap with this ThreadLocal and setter value and assigning to Thread's Threadlocals
like t.threadLocals = new ThreadLocalMap(this, firstValue);

Here parameterized constructor of ThreadLocalMap first argument is ThreadLocal Object. Now you can see the below ThreadLocalMap Constructor

ThreadLocalMap(ThreadLocal firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
table[i] = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
}

Inside of ThreadLocalMap it is taking the index as hash of the ThreadLocal only.

3) So when ever you are calling get(Thread t), it will check thread t's threadlocalmap, then it will return value.

Hope it will clear the doubts on the hash...

 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic