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 ith 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
islots, whereiis 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
WeakReferencewhoserefrefers to aThreadLocal. When a givenThreadLocalinstance is garbage collected, all entries in all threads’ maps for thatThreadLocalwill have theirreffield 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
WeakReferenceto 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 …