The principle of threadlocal non-locking thread blocking implementation in Java

Source: Internet
Author: User

While it can be said that a lot of programmers will use ThreadLocal, but I believe most programmers do not know ThreadLocal, and the use of ThreadLocal programmers mostly just know it but do not know why, therefore, Programmers using threadlocal will be imported into the trap many times, in fact, many of the high-level mechanism of Java many things are a double-edged sword, that is, the pros have their drawbacks, then our approach is to find the pros and cons of the middle balance point, the best way to solve the problem.

This article first explains what threadlocal can do, and then according to the function why use it, how to use it, finally through the internal instructions to explain his pit where to use how people should avoid the pit.

An overview of the definition and use of threadlocal (my understanding):

It is a thread-level variable, an absolute safe variable in concurrency mode, and a standard usage of thread closure (except for local variables), which is thread-safe, even if you define it as static.

What can threadlocal do?

This sentence is not good to say, we might as well look at some of the difficulties encountered in the actual project: When you are in the project according to some parameter calls into some methods, and then the method calls methods, and then call the method across objects, many layers, these methods may use some similar parameters, for example, a requires parameters A, B, C, A call B, b in the need for B, c parameters, and B calls the C method requires a, B parameters, at this time have to pass all the parameters to B, and so on, if there are many methods of invocation, the parameters will become more and more complex, in addition, when the program needs to add parameters, the relevant methods need to add parameters, Yes, very troublesome, I believe you have met, this is the C language object-oriented some of the common processing means, but our simple approach is to wrap it into an object to pass in, by increasing the object's properties can solve the problem, but the object is usually meaningful, So there are times when simple object wrapping increases some of the extended irrelevant properties that make our class definition very strange, so in these cases when we are in a complex program like this, we do it by using a class of scopes that is similar to scope, and the name and usage are more generic. Similar Web applications will have context, session, request, page level scope, and threadlocal can also solve such problems, but he is not very suitable to solve such problems, It is often in the face of these problems are not in the initial phase of the scope and the way the object is passed, that does not add parameters, when adding parameters, found to change a lot of places, in order not to break the structure of the code, there may be too many parameters, has made the code readability of the method is reduced, Add threadlocal to handle, for example, one method calls another method when passed 8 parameters, by layer by call to Nth method, passed in one of the parameters, at this time the last method needs to add a parameter, the first method becomes 9 parameters is natural, but this time, Related methods are implicated, making the code bloated.

The above mentioned threadlocal a kind of use, but it is not particularly recommended, it has some similar way to use, that is, there are a lot of dynamic calls at the framework level, the call process needs to meet some protocol, although the Protocol we will try to generalize, While many of the extended parameters are not easy to consider when defining the protocol, and the version is also ready to upgrade, but in the framework of the expansion of the interface to meet the commonality and backward compatibility, and some of the expanded content we need to threadlocal to do easy support.

To put it simply, threadlocal is a simple definition of some of the complex system extensions, making it very easy to relate the associated parameters, and here are some examples:

In spring's transaction manager, the connection obtained from the data source is put into the threadlocal, and the program is executed by threadlocal to get connection then commit and rollback, in use, To ensure that the connection that the program obtains through DataSource is obtained from spring, why do you do this, because the business code is entirely determined by the application, and the framework does not require the business code to be written, Otherwise, the framework does not let the business code to manage the benefits of connection, when the business code is cut in, spring does not pass to the business code area of a connection, it must be saved in one place, when the underlying through Ibatis, spring When a framework such as JDBC acquires the same datasource connection, it is invoked according to the rules of spring conventions, since the execution process is processed in the same thread to obtain the same connection to ensure commit, Rollback and business operations, the use of connection is the same, because only the same Conneciton can guarantee transactions, otherwise the database itself is not supported.

In fact, in many concurrent programming applications, Threadlocal plays a very important role, it does not lock, very easy to close the thread seamlessly, and will not like the local variable every time you need to allocate space, many space because it is thread-safe, so you can reuse the thread-private buffer.

How do I use threadlocal?

Define a ThreadLocal variable in any suitable position in the system, can be defined as public static type (direct new out of a ThreadLocal object), to put the data inside the use of Set (object), to get the data with Get () operation, remove the element with remove (), the rest of the methods are non-public methods, is not recommended for use.

Here is a simple example (code Snippet 1):
 public class ThreadLocalTest2 {public final static ThreadLocal <string>test_thread_name_local = new Threadlocal<string> ();p ublic final static ThreadLocal <string>test_thread_value_local = new ThreadLocal <String> ();p ublic static void Main (String[]args) {for (int i = 0; i < i++) {final String name = "Thread-" "+ I + ""; final String value = string.valueof (i); new Thread () {public void run () {try {test_thread_name_local.set (NAME); Test_thread_value_local.set (VALUE); Calla ();} finally {test_thread_name_local.remove (); Test_thread_value_local.remove ();}}}. Start ();}} public static void Calla () {callb ();} public static void Callb () {new ThreadLocalTest2 (). CALLC ();} public void Callc () {CallD ();} public void CallD () {System.out.println (Test_thread_name_local.get () + "/t=/t" + test_thread_value_local.get ());}} 

This simulates 100 threads to access the set name and value respectively, the middle deliberately set the value of name and value to the same, see if there is concurrency problem, through the output can be seen, the thread output is not sequentially output, the description is executed in parallel, and the thread name and value is can correspond to, in the middle through the call of multiple methods, in order to model the actual call parameter is not passed, how to get to the corresponding variable process, but the actual system will often cross-class, here is only in a class simulation, in fact, cross-class is the same result, we can go to the simulation on their own.

Believe to see here, many programmers are deeply interested in the principle of ThreadLocal, see how it is done, altogether parameters do not pass, but also like local variables to use it, it is really pretty magical, actually see is a set way, see the name should be related to thread, So talk less, look at its source, since we use the most is set, get and remove, then start from set:

The set (T obj) method is (code fragment 2):

public void Set (T value) {Thread T = Thread.CurrentThread (); Threadlocalmap map = getmap (t), if (map! = null) Map.set (this, value); Elsecreatemap (T, value);}

First get the current thread, and guess the same, then there is a Getmap method, passed the current thread, we can understand that the map is a thread-related map, and then if not empty, do set operation, you trace in will find, this and HashMap put operation similar, That is to write a data to the map, if it is empty, then call the Createmap method, go inside, Look (code snippet 3):

void Createmap (Thread T, T firstvalue) {t.threadlocals = new Threadlocalmap (this, firstvalue);}

The rebate creates a threadlocalmap and writes the incoming parameters and the current threadlocal as a K-V structure (code snippet 4):

Threadlocalmap (ThreadLocal Firstkey, Object firstvalue) {table = new Entry[initial_capacity];int i = Firstkey.threadlocalhashcode & (Initial_capacity-1); Table[i] = new Entry (Firstkey, firstvalue); size = 1; Setthreshold (initial_capacity);}

This does not explain the structure of the threadlocalmap details, just need to know that its implementation and HashMap similar, just a lot of methods are not, there is no implements MAP, because it does not want you through some way (such as reflection) to obtain a Map to his further operation, It is a threadlocal inside a static inner class, the default type, just under the Java.lang class can refer to it, so you can think of the thread can refer to it.

We look back at the Getmap method, because I only know that the map obtained is thread-related, and through code snippet 3, there is a t.threadlocalmap = new Threadlocalmap (this, firstvalue), I believe you should probably understand that this variable should come from thread, and we'll take a look at it according to the Getmap method:

Threadlocalmap Getmap (Thread t) {return t.threadlocals;}

Yes, it comes from thread, and this thread is exactly the current thread, so go inside and look at the definition:

Threadlocal.threadlocalmap threadlocals = null;

This property is in the thread class, where each thread has a threadlocalmap, which is used to hold thread-level local variables, and usually you can't assign them, because such assignments are usually unsafe.

Seems to be not a bit chaotic, not anxious, we look back first to explore the following ideas:

1, thread inside there is a property is similar to the same thing as HashMap, but its name is Threadlocalmap, this property is the default type, so the same package under all the classes can be referenced, because it is the thread of the local variable , so each thread has a separate map of its own that does not conflict with each other, so even if threadlocal is defined as a static thread, it does not conflict.

2, threadlocal and thread are under the same package, you can refer to this class, you can do operations on him, at this time threadlocal each definition of a, with this as key, you pass in the value as values, And this is your definition of threadlocal, so different threadlocal variables, all use set, the data will not conflict with each other, because their key is different, of course, the same threadlocal do two times set operation, will be the last one.

3, in summary, in parallel between threads, threadlocal can be used like local variables, and thread-safe, and different threadlocal variables between the data without conflict.

Let's take a look at the Get method and the Remove method, which is actually simple:

Public T get () {Thread T = Thread.CurrentThread (); Threadlocalmap map = getmap (t), if (map! = null) {Threadlocalmap.entry E = map.getentry (this); if (E! = null) return (t) e.val UE;} return Setinitialvalue ();}

By invoking the Getmap method based on the current thread, That is, call the T.threadlocalmap, and then look in the map, note that the map found in entry, which is the K-V basic structure, because you set write only the value, so, it will set a e.value to return the value you write, because key is the threadlocal itself. You can see that map.getentry is also obtained through this.

The same remove method is:

public void Remove () {Threadlocalmap m = Getmap (Thread.CurrentThread ()); if (M! = null) M.remove (this);}

Also get the map based on the current thread, remove if not empty, remove through this.

Add (2013-6-29), forget to write what the hole, this threadlocal have what pit, everyone from the front should be able to see, this threadlocal related object is bound to a map, and this map is a thread thread of a property, Then there is the question that if you do not remove it yourself or if your own program does not know when to remove it, then the thread does not log off, and the data that is set in will not be unregistered.

Conversely, write code unless you clearly recognize where the object should be set, where remove, if it is vague, it is likely that your code will not go to remove the location, or cause some logic problems, in addition, if not remove, it is necessary to wait for the thread logoff, We are in many application servers, threads are reused, because in the kernel allocation of threads still have overhead, so in these applications the thread is very difficult to be written off, then the data written to threadlocal is not easy to write off, which may inadvertently be hidden in the use of some open source framework , it is possible to cause problems, finally found that when the Oom data came from Threadlocalmap, do not know where the data is set in, so you should pay attention to this hole, perhaps more than one person fell into the pit.

The principle of threadlocal non-locking thread blocking implementation in Java

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.