The use of Java Multi-thread threadlocal and Volatite

Source: Internet
Author: User
Tags volatile

Java memory model to mask the memory differences of various hardware and operating systems to achieve cross-platform memory access effects. JLS (Java language Specification) defines a unified memory management model JMM(Java memory model)

The Java memory model specifies that all variables are stored in main memory, where the main memory is only part of the virtual machine memory, and the virtual machine memory is only part of the physical memory of the computer (the part allocated for the virtual machine process).

The Java memory model is divided into primary memory, and working memory. The main memory is shared by all the threads, and the working memory is the one that each thread has on its own, not shared.

Each thread also has its own working memory, and the thread's working memory holds a copy of the main memory copies of the variables used by the thread. All operations of a thread on a variable (read, assign) must be made in working memory and not directly read and written to variables in main memory. There is no direct access to variables in each other's working memory between threads, and the transfer of variable values between threads needs to be done through main memory, the interaction between threads, main memory, and working memory, such as:

ThreadLocal creates a copy of the variable that is created with it, and does not change because of the variable in the shared memory. Each thread uses its own copy.

As early as the version of JDK 1.2, Java.lang.threadlocal,threadlocal provides a new way to solve the concurrency problem of multi-threaded threads. Using this tool class, you can write beautiful multithreaded programs very concisely.

When you use threadlocal to maintain variables, Threadlocal provides a separate copy of the variable for each thread that uses the variable, so each thread can independently change its own copy without affecting the copy of the other thread.

From the thread's point of view, the target variable is like a thread's local variable, which is the meaning of the "local" in the class name.

Therefore, the code to write thread-local variables in Java is relatively clumsy, resulting in thread-local variables not being well-popularized in Java developers.

interface method for Threadlocal

Threadlocal class interface is very simple, there are only 4 methods, let us first look at:

    • void set (Object value) sets the value of the thread local variable for the current thread.
    • Public Object Get () This method returns the thread local variable that corresponds to the current thread.
    • The public void Remove () Removes the value of the current thread local variable to reduce memory usage, which is a new method of JDK 5.0. It is important to note that when the thread ends, the local variables of the thread that should be used are automatically garbage collected, so it is not necessary to explicitly call the method to clear the thread's local variables, but it can speed up the memory reclamation.
    • Protected Object InitialValue () returns the initial value of the thread's local variable, which is a protected method, apparently designed to allow subclasses to overwrite. This method is a deferred call method that executes only when the thread calls get () or set (Object) for the 1th time, and executes only 1 times. The default implementation in Threadlocal returns a null directly.

It is worth mentioning that, in JDK5.0, Threadlocal already supports generics, and the class name of the class has become threadlocal<t>. The API methods are also adjusted accordingly, and the new version of the API method is void set (t value), t get (), and T InitialValue ().

How does threadlocal maintain a copy of a variable for each thread? The idea is simple: there is a map in the Threadlocal class that stores a copy of the variable for each thread, the key for the element in the map is the thread object, and the value corresponds to the variable copy of the thread. We can provide a simple implementation version by ourselves:

 Packagecom.test; Public classTestnum {//① Specifies the initial value by overwriting the Threadlocal InitialValue () method with an anonymous inner class    Private StaticThreadlocal<integer> SeqNum =NewThreadlocal<integer>() {         PublicInteger InitialValue () {return0;    }    }; //② getting the next sequence value     Public intGetnextnum () {Seqnum.set (Seqnum.get ()+ 1); returnSeqnum.get (); }     Public Static voidMain (string[] args) {testnum sn=NewTestnum (); //③ 3 threads sharing sn, each generating serial numbertestclient T1 =Newtestclient (SN); TestClient T2=Newtestclient (SN); testclient T3=Newtestclient (SN);        T1.start ();        T2.start ();    T3.start (); }    Private Static classTestClientextendsThread {PrivateTestnum SN;  Publictestclient (testnum sn) { This. SN =SN; }         Public voidrun () { for(inti = 0; I < 3; i++) {                //④ 3 sequence values per threadSystem.out.println ("thread[" + thread.currentthread (). GetName () + "]--sn[" + sn.getnextnum () + "]"); }        }    }}

Each of the three threads prints out the serial number and does not affect each other. A Testnum object is common to each thread. But Getnextnum () has its own integer variable.

THREAD[THREAD-0]-sn[1]thread[thread-1]-sn[1]thread[thread-2]--sn[1]thread[ Thread-1]-sn[2]thread[thread-0]-sn[2]thread[thread-1]--sn[3]thread[ Thread-2]-sn[2]thread[thread-0]-sn[3]thread[thread-2]--sn[3]

Volatile

The Java language specification states that for optimal speed, a thread is allowed to save a private copy of a shared member variable, and is compared to the original value of a shared member variable only if the thread enters or leaves the synchronized code block. This way, when multiple threads interact with an object at the same time, it is important to notice that the thread gets the changes to the shared member variables in a timely manner. The volatile keyword is a hint to the VM: You cannot save its private copy for this member variable, but you should interact directly with the shared member variable. Usage Recommendation: Use volatile on member variables accessed by two or more threads. You do not have to use the variable you want to access when it is already in a synchronized code block, or is a constant. It is inefficient to use volatile to mask the necessary code optimizations in the VM, so use this keyword when necessary. Just like in C. Prohibit the compiler from being optimized

Final class Singleton {    privatestaticnull;     Private Singleton () {    }    publicstatic  Singleton getinstance () {         if NULL             {new  Singleton ();        }         return instance;}    }

The above code attempts to implement singleton mode, but there is a serious thread safety risk. The Java memory model defines the abstract relationship between the thread and the main memory: Shared variables between threads are stored in main memory, each thread has a private local memory (local memory), and the thread is stored locally in RAM to read/ Write a copy of the shared variable. Assuming thread1/thread2 concurrency, instance is their shared variable, communication between Thread1 and Thread2 must go through the following 2 steps:

    • Thread1 Refresh the local memory instance into main memory
    • Thread2 to main memory to read instance that have been updated before Thread1

Then one of the possible scenes--thread1 executes instance = new Singleton (), but before flushing to main memory Thread2 instance = null is still true, and then executes instance = new Singleton (), At this point two threads get two different objects, which do not match the expected one.

Final classSingleton {Private StaticSingleton instance =NULL; PrivateSingleton () {} Public StaticSingleton getinstance () {if(Instance = =NULL) {            synchronized(Singleton.class) {                if(Instance = =NULL) {instance=NewSingleton (); }            }        }        returninstance; }}

After locking and double check, there is still a risk, because in order to improve performance, the compiler and processor will often reorder the instructions, taking Singleton instance = new Singleton () as an example, it contains three instructions:

    • ① allocating memory for instance
    • ② Call Singleton constructor method
    • ③ points The instance to the allocated memory address

Three instruction execution order may be ①②③ or ①③②, after ③ execution, Instance==null will no longer be established. Possible scenarios-assuming thread1/thread2 concurrency, THREAD1 executes instructions other than ②, Thread2 's instance==null is not established, although the memory address is obtained, but the error is not called by the constructor method.

Final classSingleton {Private Static volatileSingleton instance =NULL; PrivateSingleton () {} Public StaticSingleton getinstance () {if(Instance = =NULL) {            synchronized(Singleton.class) {                if(Instance = =NULL) {instance=NewSingleton (); }            }        }        returninstance; }}

Solve the problem thoroughly by adding the volatile keyword to the instance variable. Characteristics of volatile:

    • Volatile variables are immediately flushed to main memory, and other threads can read to the new value
    • The compiler uses the concept of memory barriers to prohibit reordering of the above three instructions, allowing only the order of execution of the ①②③

Because of the above characteristics, the volatile pole is suitable for modifying the status identity in multi-threaded environments.

The use of Java Multi-thread threadlocal and Volatite

Related Article

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.