Go The threadlocal source analysis of Java multithreading Learning

Source: Internet
Author: User
Tags array length repetition thread class

(EXT) http://www.cnblogs.com/moongeek/p/7857794.html

ThreadLocal, which is a thread-local variable. It can bind a variable to a portal on a particular thread, so that each thread has a copy of the amount of change, and each thread is not affected by the same variables, and is a lightweight synchronization of shared resources.

The following is an instance of Threadlocal, where two tasks share the same variable, and both tasks set the variable to a thread-private variable, so that although both tasks "hold" the same variable, they each hold a copy of the variable. Therefore, when a thread modifies the variable, it does not affect the value of the variable in another process.

 1 public class LocalTest1 implements Runnable {2//ThreadLocal is normally set to static.         It's just a portal to set local variables for a thread, and multiple threads need only one entry 3 private static threadlocal<student> localstudent = new ThreadLocal () {4 Usually rewrite the initialization method, one will analyze the source time will explain why 5 @Override 6 public Student InitialValue () {7 return new Studen T (); 8} 9};10 private Student Student = null;12 @Override14 public void Run () {Strin G ThreadName = Thread.CurrentThread (). GetName (); System.out.println ("" "+ ThreadName +" ": Is running!"); Random ramdom = new Random (); 20//randomly generate a variable int = ramdom.nextint (+); Tem.out.println ("" "+ ThreadName +" ": Set Age to:" + age); 24//Get thread local variable, change attribute value Student stu = getstudent         (); Stu.setage (age); System.out.println ("" "+ ThreadName +" ": The first time the age value was read:" + stu.getage ()); 29 30   try {TimeUnit.SECONDS.sleep (2); 32      } catch (Interruptedexception e) {e.printstacktrace ();}35 System.out.println ("" "+ ThreadName +" ": The second read of the age value is:" + stu.getage ()); PNs}38, Public Student getstudent () {Student = loc            Alstudent.get (); 41 42//If you do not override the initialization method, you need to determine whether it is empty, and then manually assign a value of threadlocal to//if (student = = null) {44///     Student = new Student ();//Localstudent.set (student);//}47 return student;49 }50 public static void Main (string[] args) {LocalTest1 ll = new LocalTest1 ();  Read (ll, "Thread 1"), t2 thread = new Thread (ll, "Thread 2"), T1.start (), T2.start (), 58}59}60         68 public class student{62 private int age;63 + public Student () {* * *}67 public Student (int.  This.age = age;69}70 ()-Public int getage () {The return age;73-}74, public void setage (int Age) {THIS.AGE = age;77}78} 

Operation Result:

"Thread 1": Is running! "Thread 2": Is running! "Thread 2": Set Age to:45 "Thread 1": Set Age to:25 "Thread 1": The first read of the age value is: 25 "Thread 2": The first read of the age value is: 45 "Thread 1 ": The second read of the age value is: 25" Thread 2 ": The second read of the age value is: 45
1, ThreadLocal source Analysis

There are many ways to ThreadLocal the source code, but there are only three exposed public interfaces:

Public threadlocal{public  T get () {} public  void set (T value) {} public  void Remove () {}}

  set(T value)is the method of setting local variables, the source code is as follows:

1 public void Set (T value) {2       //Gets current thread 3     thread T = Thread.CurrentThread (); 4       //Gets Threadlocalmap reference for current thread, details See below 5     threadlocalmap map = getmap (t); 6       //If not empty, update the value of the local variable 7 if     (map! = NULL) 8       map.set (this, value); 9
   //if it is not the first time, first initialize the     else11       createmap (t, value);  

getMap(t)The source code is as follows, each thread variable comes with a member variable of type Threadlocalmap, which holds the member variable of the thread.

1 Threadlocalmap getmap (thread t) {2   //Return the thread's member variable THREADLOCALS3 return    t.threadlocals;4}

However, Thread defaults to setting Threadlocals to NULL, so the first time you use local variables, you need to initialize them first.

Threadlocal.threadlocalmap threadlocals = null;

  ThreadLocalMapis the inner class defined in the ThreadLocal class, and its function is to store the thread's local variables. A ThreadLocalMap reference to threadlocal is used as a key, with a local variable as the value, stored in ThreadLocalMap.Entry (a data structure that stores the key value). About ThreadLocalMap The source code, the following will be detailed introduction, here as long as the principle can be known.

  Thus we can summarize ThreadLocal the following design ideas:

    1. ThreadLocalIt's just a portal that accesses local variables.
    2. The value of the local variable exists locally on the thread Thread class, which defaults to null, and is ThreadLocal initialized only when accessed.
    3. [Threadlocalmap design ideas in the following introduction to the ThreadLocalMap source code will be analyzed]

get()is to get thread local variables, the source code is as follows:

1 public T get () {2       //Get current thread     3     Thread T = Thread.CurrentThread (); 4       //Get a threadlocals variable for current thread 5     Thr Eadlocalmap map = getmap (t); 6 if     (map! = null) {7       //If not NULL, the current threadlocal is the primary key to obtain the corresponding Entry 8       threadlocalmap.entry e = Map.getentry (this); 9< C8/>if (E! = null) {         @SuppressWarnings ("unchecked") one-         T result = (t) e.value;12         return result;13       }     }15       //If the value is null, initialize the     return Setinitialvalue (); 17}

Let's take a look at setInitialValue() the operation of the initialization function:

1 private T Setinitialvalue () {2       //Get initial default value 3     t = InitialValue (); 4       //Get current thread 5     thread T = thread.cur Rentthread (); 6       //Get the thread's Threadlocalmap reference 7     threadlocalmap map = getmap (t); 8       //NOT NULL overwrite 9     if (map! = null)         Map.set (this, value);     else12           //If NULL, initialize with the key threadlocal variable, the default value of         Createmap (t, value); 14}15 16/ /default initialization returns a null value, which is why you need to override the method. If there is no Override, the first get () operation obtains a thread-local variable of NULL, needs to be judged and manually called set () to initialize protected T InitialValue () {     return null;19}
2, Threadlocalmap source Analysis

The thread class contains a member variable threadlocals of type Threadlocalmap, which is a data structure that stores thread local variables directly. ThreadLocal is just an entrance, through the ThreadLocal operation Threadlocals, the local variable check and change operation. That's why Threadlocal exposes three of public interfaces. Also, because the key in Threadlocalmap is the ThreadLocal class, you need to set up multiple ThreadLocal if you want to set multiple local variables for a thread. Below to analyze the threadlocalmap of the source code.

  ThreadLocalMapThere are several core properties, similar to HashMap:

Table default size, size 2, for hash positioning private static final int initial_capacity = 16;//The array of key-value pairs, private entry[] table;//the critical value of the expansion, when T Able elements large to this value, will be expanded to private int threshold;

  set(T)when calling a method in Threadlocal, the Threadlocalmap method is called set(ThreadLocal, T) ,

1  private void Set (Threadlocal<?> key, Object value) {2      entry[] tab = table, 3      int len = tab.length; 4< c3/>//hash addressing, with table array length minus 1 (binary is all 1) and, so the array length must be 2 of the second side, reduce the likelihood of Hash repetition 5      int i = Key.threadlocalhashcode & (len-1); 6  7        //The subscript computed from the hash value starts traversing 8 for      (Entry e = tab[i]; 9           E! = null;10           e = tab[i = Nextindex (i, Len)]) {11
   
    //obtains the key of the entry        threadlocal<?> k = E.get ();         if the key and the same pass over, overwrite the original value, also indicates that A threadlocal variable can only hold a local variable for one thread        if (k = = key) {          E.value = value;16          return;17        }18        //key is empty, Then replace the node,        if (k = = null) {          replacestaleentry (key, value, i),          return;22        }23      }24     25      Tab[i] = new Entry (key, value); +      int sz = ++size;27        //Whether it is necessary to enlarge      if (!cleansomeslots (i, SZ) && Amp SZ >= threshold)        rehash ();  
   

Why is it that the array length of 2 is advantageous for the hash calculation to not repeat? Let's take a look, obviously, and a binary is all 1 of the number, can guarantee the maximum number of bits of the original, so the repetition probability will become smaller.

  It can be seen that Threadlocalmap uses linear detection and hashing to solve the problem of hash conflict. That is, if a hash of the array subscript is occupied, that is, the hash value is repeated, then on the basis of the subscript plus 1 test the next subscript, until a null value is found. For example, the hash calculates that the subscript i is 6,table[6] already has value, then try Table[7] is occupied, and so on, until a null value is found. The above is the method of saving thread local variables.

  Then analyze the method in the Threadlocal get() , which called the Threadlocalmap map.getEntry(this) method, and the threadlocal as a parameter passed in, return an ThreadLocalMap.Entry object (hereafter referred to as entry), the source code is as follows:

1 private Entry Getentry (threadlocal<?> key) {2       //hash computed array subscript 3     int i = key.threadlocalhashcode & (table . length-1); 4       //Get the Subscript node 5     Entry e = table[i]; 6       //If the node exists, and the key and the passed Threadlocal object is the same, the node is returned (indicating that the node does not have hash conflict processing) 7     if (E! = null && e.get () = = key) 8       return e; 9       //If the node does not meet the requirements directly, a hash conflict may be processed, then another processing of ten     Else11       Return Getentryaftermiss (key, I, E); 12}

  Again to analyze getEntryAfterMiss(ThreadLocal, int , Entry) the source code:

1//  if (e = = NULL | | E.get ()! = key) 2 private Entry Getentryaftermiss (threadlocal<?> key, int i, Entry e) {3< c1/>entry[] tab = table;  4     int len = tab.length; 5     //from the wash mark for I to start the traversal until the next empty node is encountered or the node that satisfies the requirement 6 while     (E! = null) {7         threadlocal<?> k = E.get (); 8         if (k = = key) 9             return e;10         if (k = = null) one               ///node is not empty, key is empty, the node is cleaned             expungestaleentry (i);         Else14               //I move back             i = Nextindex (i, Len);         e = tab[i];17     }18       //return null value returned     null;20}

The above is threadlocalmap a few more critical source code analysis.

  

To sum up, ThreadLocal just accesses a thread local variable of a portal, is actually stored local variables in the thread local, while ThreadLocal also as a key to hash find the location of the variable. Perhaps you would like to, why not set the Threadlocalmap to < thread,variable> type, the Thread as the primary key, but to add an intermediate module threadlocal? My idea is that, as a result, this can really meet the demand, but it is not possible to hash lookup, if a thread of local variables too much, through a linear lookup will take a lot of time, using threadlocal as the middle key, you can hash lookup, and in fact, the addition of local variables, Find and delete need to do a lot of work, the designer's idea is to encapsulate these operations in a threadlocal class, and only exposed three commonly used interfaces, if the threadlocal removed, these operations may be written in the thread class, against the design of the "unitary" principle Sunline, we do this by taking a "name" for each local variable (that is, a threadlocal corresponds to a local variable), which is convenient to use.

Go The threadlocal source analysis of Java multithreading Learning

Related Article

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.