I’m reading ThreadLocal’s source codes.And I get a question which is unable to understand.That is
why use a map to store ThreadLocal objects?I think use array is more suitable.Because you can define ThreadLocal’s hashcode from zero.And you do not need to worry about key’s collision.
Any one can help me?
Thanks in advance!
Advertisement
Answer
I think I understand what you are saying.
Internally thread locals work by generating an internal key for each the thread local variable. In recent implementations (I am looking at Java 11) the keys are generated by a hashing algorithm, and are used in the (custom) map that each thread uses to store the thread-local values.
You are proposing that these maps be replaced by simple arrays of values, and the keys are generated as sequentially increasing integers so that they can be used for subscripting the arrays. I guess you think it would improve performance and/or reduce memory.
The problem is that your idea doesn’t scale.
Suppose that an application creates a number of ThreadLocal
instances. Now suppose that a thread sets the value of the i
th ThreadLocal
for some random i
.
-
In the current implementation, an entry is created in the thread’s hash table. This takes a constant amount of space.
-
In your proposed implementation, the thread’s array now needs to have at least
i
slots, wherei
is the key. (Java arrays are not sparse!). If it doesn’t exist yet, it must be created with lengthi
. If it does exist, it may need to be reallocated with lengthi
.
When the number of ThreadLocal
instances is large enough, and they are set randomly, and only a few are set for any given thread, then the memory used by your array-based representation will be greater than for the current hash table representation.
Then, consider what happens when a ThreadLocal
is garbage collected.
-
In the current hash table implementation, each map entry is (extends) a
WeakReference
whoseref
refers to aThreadLocal
. When a givenThreadLocal
instance is garbage collected, all entries in all threads’ maps for thatThreadLocal
will have theirref
field nulled. The map’s implementation recognizes any such entries as “stale”, and when it encounters a stale entry, it expunges it from the table. -
In your proposed implementation, there is no
WeakReference
to break. Even if that could be worked around, it is difficult to see how the arrays could be compacted.
Now, the Sun / Oracle engineers who worked on the Java implementation are all smart people. And the particular engineers who implemented and maintained ThreadLocal
over the years probably looked for ways to optimize it. And they may well have considered using arrays at some point. But I imagine that they would have considered all of the pros and cons1 … before deciding on the current approach of using a hash table per thread.
It is also worth understanding the background for the current implementation. There are clues in this (fixed) bug report against the JDK 1.4 codebase: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4414045
1 – These may well have included other issues than the above ones …