Turn-java-threadlocal

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

threadlocal Introduction & jumping out of the wrong

Look at the source

Thread Exclusive variables?

Threadlocal Introduction & jumping out of the wrong

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.

Let's take a simple example.

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)

Package Concurrent;import java.util.concurrent.atomic.atomicinteger;/** * Created by Chengxiao on 2016/12/12. */public class Threadlocaldemo {public static void main (String []args) {for (int i=0;i<5;i++) {fin Al Thread T = new Thread () {@Override public void run () {System.out.print                ln ("Current thread:" +thread.currentthread (). GetName () + ", Assigned ID:" +threadid.get ());            }            };        T.start (); }} static Class threadid{//an incrementing sequence that uses Atomicinger atomic variable to ensure thread safety private static final Atomicinteger next        Id = new Atomicinteger (0); Thread local variables, associated with a unique ordinal number for each thread private static final threadlocal<integer> threadId = new THREADLOCAL&L                        T;integer> () {@Override protected Integer InitialValue () {      return nextid.getandincrement ();//equivalent to nextid++, because nextid++ this operation is a composite operation rather than an atomic operation, it will be a thread security problem (may get the same ID at initialization time, so use the atomic variable              }                };        Returns the unique sequence of the current thread, which, if first get, calls InitialValue, followed by the source to understand the public static int get () {return threadid.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-3, assigned Id:2
Look at the source

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 thread object's Threadlocalmap        if (map! = null)            Map.set (this, value);//If map is not empty, perform a set operation with the current Threadlocal object as key, The actual storage object is set for value and        else            createmap (t, value);//If map is empty, create Threadlocalmap} for the 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;//thread object holds threadlocalmap reference}

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

    Threadlocal.threadlocalmap threadlocals = 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.

Public T get () {     thread t = thread.currentthread ();//1. First gets the current thread         threadlocalmap map = Getmap (T); Gets the map object of the thread. C2/>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;         }         return Setinitialvalue ();//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 its initial value     }
Setinitialvalue
1  Private T Setinitialvalue () {2         t value = InitialValue ();//Gets the initial value 3         Thread T = Thread.CurrentThread (); 4
   threadlocalmap map = getmap (t); 5         if (map! = null) 6             map.set (this, value); 7         Else 8             createmap (t, value); 9         return value;10     }

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

1 protected T InitialValue () {2         return null;3     }

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

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 tend to employ a thread-pool mechanism, which means that threads are reusable, So every time you enter, you need to re-set, or at the end of time remove.

Turn-java-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.