Deep understanding of threadlocal

Source: Internet
Author: User

1. What is threadlocal?

Threadlocal, as its name implies, is not a thread, but a localized object of the thread. When threadlocal is used to maintain a variable for a multi-threaded object, threadlocal allocates an independent copy of the initialization variable for each thread that uses the variable. Therefore, each thread can change its own copy independently without affecting the copies corresponding to other threads. From the thread perspective, this variable is like a local variable of the thread, which is also the meaning of "local" in the class name.


Here is an example:

Public class threadlocaltest1 {Private Static index num = new index (); // create an index-type local variable Private Static threadlocal <index> Local = new threadlocal <index> () {@ overrideprotected index initialvalue () {return num; // note that here, the returned object is a defined object num, instead of the new index () --> the returned object is not a copy }}; public static void main (string [] ARGs) throws interruptedexception {thread [] threads = new thread [5]; for (INT I = 0; I <5; I ++) {threads [I] = new thread (New runnable () {@ overridepublic void run () {// retrieve the local variable of the current thread and accumulate the Index = Local for five times. get (); For (INT I = 0; I <5; I ++) {index. increase ();} // reset the local variable after accumulation. set (INDEX); system. out. println (thread. currentthread (). getname () + ":" + index. num) ;}}, "thread-" + I) ;}for (thread: threads) {thread. start () ;}} static class index {int num; Public void increase () {num ++ ;}}}
The running result is as follows:

Thread-0 : 5Thread-1 : 10Thread-3 : 15Thread-2 : 20Thread-4 : 25
We will find that the results of each run are different. Why is this happening?

In the above Code, we provide the initial value for our threadlocal by overwriting the initialvalue function. Each thread will obtain a copy of the initial value. Now our initial value is a defined object, num is a reference to this object. In other words, our initial value is a reference, and the reference copy of the thread points to the same object. For example:


Transformation: Create a copy of the object instead of a copy of the object application

// Create an index-type local variable Private Static threadlocal <index> Local = new threadlocal <index> () {@ overrideprotected index initialvalue () {return New Index (); // note here }};


Let's look at another example:

Public class threadlocaltest2 {// create an integer-type thread local variable public static final threadlocal <integer> Local = new threadlocal <integer> () {@ overrideprotected integer initialvalue () {return 0 ;}; public static void main (string [] ARGs) throws interruptedexception {thread [] threads = new thread [5]; for (INT I = 0; I <5; I ++) {threads [I] = new thread (New runnable () {@ overridepublic void run () {// obtain the local variable of the current thread, then add int num = Local 5 times. get (); For (INT I = 0; I <5; I ++) {num ++;} // reset the local variable after accumulation. set (Num); system. out. println (thread. currentthread (). getname () + ":" + local. get () ;}, "thread-" + I) ;}for (thread: threads) {thread. start ();}}}
The running result is as follows:

Thread-4 : 5Thread-1 : 5Thread-2 : 5Thread-0 : 5Thread-3 : 5
We can see that the result after each thread is accumulated is 5, each thread processes its own local variable value, and the threads do not affect each other.


Ii. threadlocal Interface Method

Threadlocal is actually very simple from the code. When each thread calls the set method, it is equivalent to adding a record to the internal map, and the key is the respective thread, value is the value put in the Set called by each thread.

Public void set (object Value) sets the value of the local variable of the current thread;

Public object get () returns the local variable of the thread corresponding to the current thread;

Public void remove () deletes the local variable value of the current thread to reduce memory usage. This method is newly added to JDK 5.0. It should be noted that when the thread ends, the local variables of the thread will be automatically reclaimed, so explicitly calling this method to clear the local variables of the thread is not a required operation, but it can speed up memory recovery;

    Protected object initialvalue () returns the initial value of the local variable of the thread. This method is a protected method, apparently designed to overwrite the subclass. This method is a delayed call method. It is executed only once when the thread calls get () or set (object) for 1st times. The default implementation in threadlocal directly returns a null value.

    We can also implement a simple threadlocal by ourselves:
      Public class simplethreadlocal {private map = collections. synchronizedmap (New hashmap (); Public void set (Object newvalue) {// The key is the thread object, and the value is the map of the variable copy of the thread. put (thread. currentthread (), newvalue);} public object get () {thread currentthread = thread. currentthread (); // return the object OBJ = map variable corresponding to this thread. get (currentthread); // If the map does not exist, store it in the map. If (OBJ = NULL &&! Map. containskey (currentthread) {OBJ = initialvalue (); map. put (currentthread, OBJ);} return OBJ;} public void remove () {map. remove (thread. currentthread ();} public object initialvalue () {return NULL ;}}

      Iii. Comparison between threadlocal and synchronization mechanism

      What are the advantages of threadlocal over thread synchronization? Threadlocal and thread synchronization mechanisms are designed to solve the access conflict between the same variables in multiple threads.

      In the synchronization mechanism, the object lock mechanism ensures that only one thread accesses the variable at a time. At this time, the variable is shared by multiple threads. The synchronization mechanism requires the program to carefully analyze when to read and write the variable, and when to lock an object, when to release the object lock and other complicated issues, it is relatively difficult to design and write the program.

      Threadlocal solves multi-thread concurrent access from another perspective. Threadlocal provides an independent copy of variables for each thread, thus isolating multiple threads from Data Access conflicts. Because every thread has its own copy of the variable, there is no need to synchronize the variable. Threadlocal provides thread-safe object encapsulation. When writing multi-threaded code, you can encapsulate insecure variables into threadlocal.

      To sum up, for the problem of multi-thread resource sharing, the synchronization mechanism adopts the "time-for-space" approach: Access serialization and object sharing. Threadlocal adopts the "space-for-time" method: parallel access and exclusive object. The former provides only one copy of the variable, allowing different threads to queue for access, while the latter provides a copy of the variable for each thread. Therefore, the former can be accessed simultaneously without affecting each other.

    Iv. Practical Application

    1. Use in hibernate:

    Public class hibernateutil {Private Static log = logfactory. getlog (hibernateutil. class); // defines sessionfactoryprivate static final sessionfactory; // creates a thread local variable session to save the sessionpublic static final threadlocal local of hibernate = new threadlocal (); static {try {// use the default configuration file hibernate. cfg. XML creates sessionfactorysessionfactory = new configuration (). configure (). buildsessionfactory ();} catch (Th Rowable ex) {log. Error ("failed to initialize sessionfactory! ", Ex); throw new exceptionininitializererror (Ex) ;}/ *** get the session in the current thread * @ return session * @ throws hibernateexception */public static session currentsession () throws hibernateexception {session = (Session) Local. get (); // if the session has not been enabled, a new sessionif (session = NULL) {session = sessionfactory will be created. opensession (); Local. set (session); // Save the new session to the local variable} return session;} public static void C Losesession () throws hibernateexception {// gets the local variables of the thread and forcibly converts them to session-type session = (Session) Local. get (); Local. set (null); If (session! = NULL) Session. Close ();}}

    2. Use in transaction control:

    Another blog record will be written.

5. References:1. http://stamen.iteye.com/blog/15351202. http://my.oschina.net/clopopo/blog/1493683. http://lavasoft.blog.51cto.com/62575/51926/




Deep understanding of threadlocal

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.