Java concurrent programming principle and Combat 25: Threadlocal The use and principle of thread local variables

Source: Internet
Author: User
Tags thread class unique id variable scope

1. What is threadlocal

Threadlocal is a thread-local variable as the name implies. This variable is different from the normal variable, which is accessed by the get and set methods in each thread, each with its own independent copy of the variable. Thread local variables do not have multiple threads working on the same variable at the same time, so there is no thread security issue.

Use of 2.ThreadLocal variables

 Public classThreadlocaldemo {PrivateThreadlocal<integer> ThreadLocal =NewThreadlocal<integer>(){        //Initialize the value of a local variable@OverrideprotectedInteger InitialValue () {return NewInteger (0);    }    };  Publicinteger getNext () {integer value=Threadlocal.get (); Value++;        Threadlocal.set (value); returnvalue; }     Public Static voidMain (string[] args) {Executorservice executor= Executors.newfixedthreadpool (5); FinalThreadlocaldemo demo =NewThreadlocaldemo (); Executor.execute (NewRunnable () {@Override Public voidrun () { while(true) {System.out.println (Thread.CurrentThread (). GetName ()+ ": " +Demo.getnext ());        }            }        }); Executor.execute (NewRunnable () {@Override Public voidrun () { while(true) {System.out.println (Thread.CurrentThread (). GetName ()+ ": " +Demo.getnext ());    }            }        }); }}

3. Jump out of threadlocal misunderstanding

  Threadlocal is generally referred to as thread-local variables, a special thread-binding mechanism that binds variables to threads and maintains a separate copy of the variable for each thread. By threadlocal, you can limit the visible scope of an object to the same thread.

Jump out of the wrong

It is important to emphasize that do not use threadlocal and synchronized analogy, because this comparison is meaningless! Sysnchronized is a mutually exclusive synchronization mechanism to ensure proper access to shared resources in a multithreaded environment. In essence, Threadlocal provides a "thread-level" variable Scope , which is a thread-gated (per-thread-exclusive variable) technique, and, more frankly, Threadlocal can be understood to limit the scope of an object to a thread context , making the scope of the variable " thread-level ."

When there is no threadlocal, a thread may pass through multiple levels in its declaration cycle, multiple methods, if there is an object that needs to be called multiple times within this thread cycle, and is a cross-level (intra-thread share), the usual practice is to pass through parameters While threadlocal binds the variable on the thread, it is easy to get to the object with the Get method provided by it, regardless of where you are in a threading cycle. Greatly improves access convenience for thread-level variables.

Suppose we want to associate a unique ordinal number for each thread, we need to access the serial number multiple times during each thread cycle, and then we can use threadlocal. (Of course, the following example does not fully reflect the cross-hierarchy cross-method calls, understanding is possible)

 Packageconcurrent;ImportJava.util.concurrent.atomic.AtomicInteger;/*** Created by Chengxiao on 2016/12/12.*/ Public classThreadlocaldemo { Public Static voidMain (String []args) { for(inti=0;i<5;i++){            FinalThread T =NewThread () {@Override Public voidrun () {System.out.println ("Current thread:" +thread.currentthread (). GetName () + ", Assigned ID:" +threadid.get ());            }            };        T.start (); }    }    Static   classthreadid{//an incrementing sequence that uses Atomicinger atomic variables to ensure thread safety        Private Static FinalAtomicinteger NextID =NewAtomicinteger (0); //thread-local variables, associated with a unique ordinal number for each thread        Private Static FinalThreadlocal<integer> threadId =NewThreadlocal<integer>() {@OverrideprotectedInteger InitialValue () {returnNextid.getandincrement ();//equivalent to nextid++, because nextid++ is a composite operation rather than an atomic operation, it can be a thread-safe problem (it may get the same ID at initialization time, so use an atomic variable                    }                }; //returns the unique sequence of the current thread, which, if first get, calls InitialValue, followed by the source to see         Public Static intget () {returnThreadid.get (); }    }}

As a result of the execution, you can see that each thread is assigned a unique ID, and we can get it directly from "anywhere" within the scope of this thread, Threadid.get ().

Current thread: Thread-4, assigned id:1 current thread: Thread-0, assigned id:0 current thread: Thread-2, assigned Id:3 current thread: Thread-1, Assigned Id:4 Current thread: Thread

4.ThreadLocal principle

Set operation, binding variable for thread

 public  void   set (T value) {Thread T  = Thread.CurrentThread (); //        1. First gets the current thread object  Threadlocalmap map = getmap (t); //        2. Gets the threadlocalmap of the thread object  if  (Map! = null   this , value); //  else   Createmap (T, value);  // } for that thread 

As you can see, threadlocal is just an entry, and the real variable is bound on the thread.

threadlocalmap Getmap (Thread t) {    return t.threadlocals;   The Thread object holds a reference to Threadlocalmap }

Here is the definition in the thread class, where each thread object has a Threadlocalmap object

null;

Now, we can see Threadlocal's design idea:

1.ThreadLocal is just a variable access entry;

2. Each thread object has a Threadlocalmap object, and this threadlocalmap holds a reference to the object;

3.ThreadLocalMap takes the current Threadlocal object as key, with the true storage object as value. The object that is bound to the current thread can be found by the threadlocal instance on get.

At first glance, the design does seem to be a bit around. We can completely design this form into map<thread,t>, where a thread corresponds to a storage object. There are two main purposes of this design: threadlocal

One is to ensure that the relevant objects can be recovered as soon as possible at the end of the current thread, and that the elements in the threadlocalmap are greatly reduced, and we all know that the map is too large to cause hash collisions and result in poor performance.

Let's look at the Get method again.

 PublicT Get () {Thread T= Thread.CurrentThread ();//1. Get the current thread firstThreadlocalmap map = getmap (t);//2. Get the Map object for the thread         if(Map! =NULL) {//3. If map is not empty, take the threadlocal instance as key to get to the corresponding entry, and then remove the object from the entry. Threadlocalmap.entry e = Map.getentry ( This); if(E! =NULL)                 return(T) E.value; }         returnSetinitialvalue ();//if the map is empty, that is, the first time you do not call set direct get (or call the set, and then call Remove), set the initial value}
Setinitialvalue
Private T Setinitialvalue () {        = InitialValue ();   Gets the initial value of        Thread t = thread.currentthread (        ); = Getmap (t);         if NULL )            Map.set (this, value);         Else             createmap (t, value);         return value;    }

The InitialValue method, by default, is null, and the access permission is protected, which allows overrides.

protected T InitialValue () {    returnnull;    }

When it comes to this, we should have a certain understanding of Threadlocal's design objectives and design ideas.

5. Thread Exclusive variables

There is also a question that will cause confusion, and we say that Threadlocal maintains a separate copy of the variable for each thread, so is it true that each thread really does not affect the object's "full autonomy" without affecting the objects of other threads? In fact, this is not a discussion of threadlocal, but for what purpose do you use threadlocal. If the objects we associate with a thread are "completely exclusive", that is, each thread has a full set of object references in the stack and objects in the heap , then in this case it is a truly thorough "thread-exclusive variable ", equivalent to a deep copy, Each thread plays its own, and any action on that object does not have any effect on other threads.

In another more general case, the so-called exclusive copy of the variable, in fact, each thread has a separate object reference, and the object in the heap is shared between the threads , in this case, the nature will still involve access to the shared resources, still the risk of thread insecurity. So, threadlocal can't solve the thread safety problem.

Therefore, it is up to your application that you do not need to fully isolate variables and complete isolation. It can be imagined that when the object is too large, if each thread has such a "deep copy", concurrency is relatively large, the pressure on the server is naturally very large. Like the Servlet,servlet in web development is thread insecure, a request thread, multiple threads share a Servlet object, and in the early CGI design, n requests correspond to n objects, and the performance is naturally poor after a large amount of concurrency.

Threadlocal has emerged in spring's transaction management, including Hibernate session management, which in web development is sometimes used to manage user session HttpSession,
This typical request-first-thread scenario in web interaction seems to be more suitable for use with threadlocal, but it is important to note that because the session is associated with threads at this point, Tomcat's Web servers use a thread-pool mechanism.
This means that the thread is reusable, so you need to re-set it every time you enter it, or remove it at the end of time.

Threadlocal Thread Safety Case

Resources:

"Java Concurrent programming Combat" dragon Fruit College

Java concurrent programming principle and Combat 25: Threadlocal The use and principle of thread local variables

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.