Correct understanding of threadlocal

Source: Internet
Author: User

First, threadlocal is not used to solve the problem of multi-threaded access to shared objects. Generally, threadlocal is used. the objects from set () to the thread are the objects used by the thread. Other threads do not need to be accessed or cannot be accessed.Different threads access different objects.

In addition, threadlocal enables each thread to maintain an independent object instead of threadlocal. set () is implemented, but through the operation of the new object in each thread. Each thread creates one object, not a copy or copy of the object.Through threadlocal. set () saves the reference of the newly created object to a map of each thread. Each thread has such a map and runs threadlocal. in get (), each thread extracts the objects from its own map, so it obtains the objects in its own thread, and the threadlocal instance is used as the map key.

If threadlocal. set () is the same object shared by multiple threads, so threadlocal of multiple threads. get () still gets the shared object itself, but there are still concurrent access problems.

Here is a typical threadlocal application in hibernate:

JavaCode

  1. Private Static FinalThreadlocal threadsession =NewThreadlocal ();
  2. Public StaticSession getsession ()ThrowsInfrastructureexception {
  3. Session S = (Session) threadsession. Get ();
  4. Try{
  5. If(S =Null){
  6. S = getsessionfactory (). opensession ();
  7. Threadsession. set (s );
  8. }
  9. }Catch(Hibernateexception ex ){
  10. Throw NewInfrastructureexception (Ex );
  11. }
  12. ReturnS;
  13. }

you can see that in the getsession () method, first check whether the current thread has been put into the session. If not, use sessionfactory (). opensession () creates a session and then sets the session to the thread. It is actually placed in the map threadlocalmap of the current thread, the only reference to this session is the threadlocalmap in the current thread (as described below), and threadsession is the key of this value. To obtain this session, you can use threadsession. get () to get the threadlocalmap in the current thread, and then take threadsession as the key to get the corresponding value. This session is equivalent to the private variable of the thread, rather than the public variable.
obviously, this session cannot be obtained in other threads, and they can only get things in their own threadlocalmap. If the session is shared by multiple threads, it will not be messy.
imagine how to implement it without threadlocal? It may be troublesome to create a session in the action and upload the session to the service and Dao one by one. Alternatively, you can define a static map by yourself and put the current thread as the key and session created as the value into the map. This is also the idea of the average person, but in fact, the implementation of threadlocal is the opposite. It has a map in each thread, and the threadlocal instance is used as the key, so that the number of items in each map is very small, in addition, when the thread is destroyed, the corresponding items are also destroyed. I don't know what other benefits are there.

In short, threadlocal is not used to solve the problem of shared object access, but mainly provides methods to keep objects and convenient object access methods to avoid passing parameters. Two points are summarized:
1. Each thread has its own threadlocalmap class object, which can keep the thread's own objects in it. The thread can correctly access its own objects in various tubes.
2. Use a shared threadlocal static instance as the key, save the references of different objects to threadlocalmap of different threads, and then run get () of the static threadlocal instance everywhere () method to get the object saved by the thread, avoiding the trouble of passing this object as a parameter.

Of course, if you want to pass the thread-shared object through threadlocal. set () can also be placed in the thread to avoid the access method passed by parameters. However, note that get () is the same shared object, concurrent access problems must be solved by other means. But in general, the objects shared by the thread can be easily accessed by setting them to a certain type of static variables. It seems that there is no need to put them in the thread.

In the Application Scenario of threadlocal, I think it is best to access objects with multiple threads (each thread corresponds to an instance), and this object is used in many places.

Next let's take a look at the implementation principle of threadlocal (jdk1.5 source code)

Java code

  1. Public ClassThreadlocal <t> {
  2. /** 
  3. * Threadlocals rely on per-thread hash maps attached to each thread 
  4. * (Thread. threadlocals and inheritablethreadlocals). The threadlocal 
  5. * Objects Act as keys, searched via threadlocalhashcode. This is 
  6. * Custom hash code (useful only within threadlocalmaps) that eliminates 
  7. * Collisions in the common case where consecutively constructed 
  8. * Threadlocals are used by the same threads, while remaining well-behaved 
  9. * In less common cases. 
  10. */
  11. Private Final IntThreadlocalhashcode = nexthashcode ();
  12. /** 
  13. * The next hash code to be given out. accessed only by like-named method. 
  14. */
  15. Private Static IntNexthashcode =0;
  16. /** 
  17. * The difference between successively generated hash codes-turns 
  18. * Implicit sequential thread-local IDS into near-optimally spread 
  19. * Multiplicative hash values for power-of-two-sized tables. 
  20. */
  21. Private Static Final IntHash_increment =0x61c88647;
  22. /** 
  23. * Compute the next hash code. The static synchronization used here 
  24. * Shocould not be a performance bottleneck. When threadlocals are 
  25. * Generated in different threads at a fast enough rate to regularly 
  26. * Contend on this lock, memory contention is by far a more serious 
  27. * Problem than lock contention. 
  28. */
  29. Private Static Synchronized IntNexthashcode (){
  30. IntH = nexthashcode;
  31. Nexthashcode = H + hash_increment;
  32. ReturnH;
  33. }
  34. /** 
  35. * Creates a thread local variable. 
  36. */
  37. PublicThreadlocal (){
  38. }
  39. /** 
  40. * Returns the value in the current thread's copy of this thread-Local 
  41. * Variable. Creates and initializes the copy if this is the first time 
  42. * The thread has called this method. 
  43. * @ Return the current thread's value of this thread-Local 
  44. */
  45. PublicT get (){
  46. Thread t = thread. currentthread ();
  47. Threadlocalmap map = getmap (t );
  48. If(Map! =Null)
  49. Return(T) map. Get (This);
  50. // Maps are constructed lazily. If the map for this thread
  51. // Doesn't exist, create it, with this threadlocal AND ITS
  52. // Initial value as its only entry.
  53. T value = initialvalue ();
  54. Createmap (T, value );
  55. ReturnValue;
  56. }
  57. /** 
  58. * Sets the current thread's copy of this thread-local variable 
  59. * To the specified value. Maximum applications will have no need 
  60. * This functionality, relying solely on the {@ link # initialvalue} 
  61. * Method to set the values of thread-locals. 
  62. * @ Param value the value to be stored in the current threads 'Copy 
  63. * This thread-local. 
  64. */
  65. Public VoidSet (T value ){
  66. Thread t = thread. currentthread ();
  67. Threadlocalmap map = getmap (t );
  68. If(Map! =Null)
  69. Map. Set (This, Value );
  70. Else
  71. Createmap (T, value );
  72. }
  73. /** 
  74. * Get the map associated with a threadlocal. overridden in 
  75. * Inheritablethreadlocal. 
  76. * @ Param t the current thread 
  77. * @ Return the map 
  78. */
  79. Threadlocalmap getmap (thread t ){
  80. ReturnT. threadlocals;
  81. }
  82. /** 
  83. * Create the map associated with a threadlocal. overridden in 
  84. * Inheritablethreadlocal. 
  85. * @ Param t the current thread 
  86. * @ Param firstvalue value for the initial entry of the map 
  87. * @ Param map the map to store. 
  88. */
  89. VoidCreatemap (thread t, t firstvalue ){
  90. T. threadlocals =NewThreadlocalmap (This, Firstvalue );
  91. }
  92. .......
  93. /** 
  94. * Threadlocalmap is a customized hash map suitable only 
  95. * Maintaining thread local values. No operations are exported 
  96. * Outside of the threadlocal class. The class is package private 
  97. * Allow declaration of fields in class thread. To help deal 
  98. * Very large and long-lived usages, the hash table entries use 
  99. * Weakreferences for keys. However, since reference queues are not 
  100. * Used, stale entries are guaranteed to be removed only when 
  101. * The table starts running out of space. 
  102. */
  103. Static ClassThreadlocalmap {
  104. ........
  105. }
  106. }

We can see that the variables in the threadlocal class only have the three int types:

Java code
    1. Private Final IntThreadlocalhashcode = nexthashcode ();
    2. Private Static IntNexthashcode =0;
    3. Private Static Final IntHash_increment =0x61c88647;

The variables used as threadlocal instances are only threadlocalhashcode. nexthashcode and hash_increment are static variables of the threadlocal class. In fact, hash_increment is a constant, it indicates the increment of threadlocalhashcode values of two consecutive threadlocal instances, while nexthashcode indicates the value of threadlocalhashcode of the next threadlocal instance to be allocated.

Let's take a look at what operations are performed when a threadlocal instance is created, that is, new threadlocal (). From the above we can see that there are no operations in the constructor threadlocal (). The only operation is this sentence:

Java code
    1. Private Final IntThreadlocalhashcode = nexthashcode ();

So what does nexthashcode () do:

Java code
    1. Private Static Synchronized IntNexthashcode (){
    2. IntH = nexthashcode;
    3. Nexthashcode = H + hash_increment;
    4. ReturnH;
    5. }

The next hashcode value of the threadlocal class is the value of nexthashcode assigned to the threadlocalhashcode of the instance, and then the value of nexthashcode increases the value of hash_increment.

Therefore, the variables of the threadlocal instance only have this threadlocalhashcode and are final to distinguish different threadlocal instances. The threadlocal class is mainly used as a Tool class, so threadlocal. where is the object set () stored?

Take a look at the Set () method above and combine the two sentences

Java code
    1. Threadlocalmap map = thread. currentthread (). threadlocals;

This threadlocalmap class is an internal class defined in threadlocal, but its instance is used in the Thread class:

Java code
    1. Public ClassThreadImplementsRunnable {
    2. ......
    3. /* Threadlocal values pertaining to this thread. This map is maintained 
    4. * By the threadlocal class .*/
    5. Threadlocal. threadlocalmap threadlocals =Null;
    6. ......
    7. }

Let's look at this sentence again:

Java code
    1. If(Map! =Null)
    2. Map. Set (This, Value );

That is, the threadlocal instance is used as the key, and the object to be maintained is set to threadlocalmap of the current thread.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.