Java multithreaded 9:threadlocal source code Analysis

Source: Internet
Author: User

Threadlocal Source Code Analysis

Threadlocal is actually quite simple, because there are three public methods in the class: set (T value), get (), remove (). The first analysis of the source clearly know threadlocal is what to use, reuse, the final summary, explain threadlocal take such ideas.

Three theoretical foundations

In the analysis of Threadlocal source code, first talk about the threadlocal of the three theoretical basis:

1. Each thread has its own Threadlocal.threadlocalmap object

2, each Threadlocal object has a loop counter

3, Threadlocal.get () value, is based on the current thread, get the thread's own threadlocal.threadlocalmap, and then in this map according to the 2nd loop counter to obtain a specific value

Two Math problems

1, Threadlocal.threadlocalmap stipulates that the size of the table must be 2 n power

/***/private  entry[] table;

Because from the computer's point of view, the bitwise operation is more efficient than the mathematical operation

int i = firstkey.threadlocalhashcode & (initial_capacity-1);

For example, the current table length is 16, then 16-1=15, which is the binary 1111. Now there is a number 23, which is the binary 00010111. 23%16=7, take a look at the & operation:

00010111

&

00001111 =

00000111

00000111 is 7, as with the result of the modulo operation, the efficiency is high instead.

2, the hash increment is set to 0x61c88647, that is, threadlocal through the way to obtain a table of a position, will be in the original threadlocalhashcode on the basis of adding 0x61c88647

/***/privatestaticfinalint hash_increment = 0x61c88647 ;

Although I do not know why, but from the point of view of Table.length, try the case of length 16 and 32:


7 14 21 28 3 10 17 24 31 6 13 20 27 2 9 16 23 30 5 12 19 26 1 8 15 22 29 4 11 18 25 0

This avoids the hash conflict, and the next two numbers are more scattered. And after the n power of 2, the first number starts to circulate, which means that Threadlocalhashcode can start anywhere.

With these theoretical bases, we can look at the implementation principle of several methods of threadlocal.

Set (T value)

A little bit look at set source code

 Public void set (T value) {        = thread.currentthread ();         = Getmap (t);         if NULL )            Map.set (this, value);         Else             createmap (t, value);    }
threadlocalmap Getmap (Thread t) {        return  t.threadlocals;    }
/**/null;

As in the previous lecture:

1. Get the current thread

2. Get the Threadlocal.threadlocalmap inside the thread

3, see if this threadlocal.threadlocalmap exists, there is a value set, does not exist to give the thread to create a Threadlocal.threadlocalmap

The 3rd has two branches, looking at the simple branch that creates the map:

void Createmap (Thread T, T firstvalue) {        new threadlocalmap (this, firstvalue);    }
Threadlocalmap (ThreadLocal firstkey, Object firstvalue) {            new  entry[initial_capacity];             int i = firstkey.threadlocalhashcode & (initial_capacity-1);             New Entry (Firstkey, firstvalue);             = 1;            Setthreshold (initial_capacity);        }
Private Final int threadlocalhashcode = nexthashcode ();
Private Static int Nexthashcode () {    return  nexthashcode.getandadd (hash_increment);     }
Private Static Atomicinteger Nexthashcode =     new  Atomicinteger ();

There is no next node in this map, so it has to be said that Threadlocalmap is a somewhat misleading name, although it is called a map, but in fact it is stored in a way that is not a list method but an address method . When you see the position in the table, add a static nexthashcode, which means that the same value of set, There may be different locations in the table in each threadlocal.threadlocalmap, but that's okay.

OK, after reading the branch you created, take a look at the branch you set:

Private voidset (ThreadLocal key, Object value) {//We don ' t use a fast path as with get () because it 's at//least as common to use Set () to create new entries as//it is-to-replace existing ones, in which case, a fast//path would fail more often than not.entry[] Tab=table; intLen =tab.length; inti = Key.threadlocalhashcode & (len-1);  for(Entry e =Tab[i]; E!=NULL; E= Tab[i =Nextindex (i, Len)]) {ThreadLocal k=E.get (); if(k = =key) {E.value=value; return; }                if(k = =NULL) {replacestaleentry (key, value, I); return; }} Tab[i]=NewEntry (key, value); intSZ = + +size; if(!cleansomeslots (i, SZ) && sz >=threshold) rehash (); }
Private Static int nextindex (intint  len) {            return ((i + 1 < len), I + 1:0); 
    }

To get a sense of logic, set a few steps:

1, first to threadlocal inside the Threadlocalhashcode to get to a table in the position

2. If there is data in this position, get the threadlocal on this position

(1) Judge the position of the threadlocal and I myself this threadlocal is not a threadlocal, is the word data on the cover, return

(2) Not the same threadlocal, and then judge the position of the threadlocal is not empty, this explanation. Entry is ThreadLocal weak reference, "static class Entry extends Weakreference<threadlocal>", It is possible that the threadlocal was garbage collected, replacing the newly set value with the current position and returning

(3) There is no return, to mold plus 1, to see the mold plus 1 after the table position is not empty, is empty and add 1, judge the position is not empty ... Until you find a location on the table that is not empty, put a value in it. In other words, when there is data in the position of the table, Threadlocal takes the method of finding the nearest empty location to set the data .

Get ()

If the set (T value) is understood clearly, get () is well understood:

 public   T get () {Thread T  = Thread.CurrentThread ();        Threadlocalmap map  = Getmap (t);  if  (Map! = null   = map.getentry (this  );  if  (E! = null  )  return   (T) E.value;     return   Setinitialvalue (); }
Private Entry getentry (ThreadLocal key) {            int i = key.threadlocalhashcode & (table.length-1); 
    = table[i];             if null && e.get () = = key                )return  e            ; Else                return Getentryaftermiss (Key, I, E);        }
PrivateEntry Getentryaftermiss (ThreadLocal key,intI, Entry e) {entry[] tab=table; intLen =tab.length;  while(E! =NULL) {ThreadLocal k=E.get (); if(k = =key)returne; if(k = =NULL) Expungestaleentry (i); ElseI=Nextindex (i, Len); E=Tab[i]; }            return NULL; }

To take a step at a moment:

1. Get the current thread

2, try to be the front of the threadlocal.threadlocalmap to take it

3, the current thread to determine whether there is threadlocal.threadlocalmap

(1) have to try according to the current threadlocal Threadlocalhashcode to take the value of the table, there is return, not to Die plus 1 continue to find, this and set the algorithm is the same

(2) Set an initial value for the current thread threadlocal.threadlocalmap without calling the Set method

Remove ()

The Remove method is very simple:

 Public void Remove () {         = getmap (Thread.CurrentThread ());          if NULL )             M.remove (this);     }

Get the current thread of the Threadlocal.threadlocalmap, if there is Threadlocal.threadlocalmap, find the corresponding entry, remove it just fine

Summarize

The above analysis of so many source code, is more detailed to see threadlocal. To make a summary of these contents, the principle of threadlocal is simply that:

1, threadlocal does not need key, because the thread inside of its own threadlocal.threadlocalmap is not the use of linked list method to achieve, but by the open address method to achieve

2. Each time set, the Threadlocal.threadlocalmap in the thread inside the table array in a position of a value, this position by the threadlocal in the Threadlocalthashcode to get a model, if there is data on the position, then look for a no number Location of the data

3, each get the same time, according to Threadlocal in the Threadlocalhashcode to take the mold, Take a position in the table in the Threadlocal.threadlocalmap in the thread, see if there is any data, and go to the next location.

4, since Threadlocal no key, then a threadlocal can only plug a specific data. If you want to plug data into a table in a threadlocal.threadlocalmap inside a thread, say you want to plug in three strings, an integer, two double, a date, define multiple threadlocal, ThreadLocal supports generics "public class threadlocal<t>".

Java multithreaded 9:threadlocal source code Analysis

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.