Thread local change, i.e. threadlocal-->spring transaction management

Source: Internet
Author: User
Tags sessions

We know that spring has reduced the difficulty of developers using a variety of data persistence technologies through a variety of template classes. These template classes are thread-safe, meaning that multiple DAO can reuse the same template instance without conflicts. We use the template class to access the underlying data, and depending on the persistence technology, the template class needs to bind the resources of the data connection or session. However, these resources are inherently non-thread-safe, meaning that they cannot be shared by multiple threads at the same time. Although the template class obtains a data connection or session through a resource pool, the resource pool itself addresses the caching of data connections or sessions and is not a thread-safe issue for data connections or sessions.

In the traditional experience, if an object is non-thread-safe, access to the object must be thread-synchronized with synchronized in a multithreaded environment. However, the template class does not adopt the thread synchronization mechanism because thread synchronization reduces concurrency and affects system performance. In addition, the challenge of addressing thread safety through code synchronization can be much more difficult to implement several times. So what kind of magic can a template class rely on to resolve thread-safety problems without thread synchronization?The answer is threadlocal!.

Threadlocal play an important role in spring, in the management of the request scope of the bean, transaction management, task scheduling, AOP and other modules have appeared their figure, play a pivotal role. To understand the underlying technology of spring transaction management, Threadlocal is the fortress of the hill that must be conquered.

What is threadlocal?

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.
ThreadLocal, as the name implies, is not a thread, but a localized object of a thread. When an object working in multi-threading uses threadlocal to maintain a variable, threadlocal assigns a separate copy of the variable to each thread that uses the variable. So each thread can change its own copy independently, without affecting the copy of the other thread. From the thread's point of view, this variable is like a thread's local variable, which is the meaning of the "local" in the class name.

Thread-local variables are not a new Java invention, and many languages (such as IBM XL, FORTRAN) provide thread-local variables at the syntactic level. Language-level support is not available in Java, and support is provided through threadlocal classes in a workaround. Therefore, the code to write thread-local variables in Java is relatively awkward, which is why thread-local variables are not well-developed among Java developers.


interface method for Threadlocal

Threadlocal class interface is very simple, there are only 4 methods, let's look at it first.

      • 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 variables corresponding to the current thread;
      • 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 on the thread should be garbage collected automatically, so it is not necessary to explicitly call the method to clear the local variables of the thread, but it can speed up the memory recovery;
      • Protected Object InitialValue ()
      • Returns the initial value of the thread's local variable, which is a protected method, apparently designed for 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:

Code Listing 9-3 simplethreadlocal

Java code
  1. Public class Simplethreadlocal {
  2. private Map ValueMap = Collections.synchronizedmap (new HashMap ());
  3. public void Set (Object newvalue) {
  4. The //① key is a thread object, and the value is a copy of the variable for this thread
  5. Valuemap.put (Thread.CurrentThread (), newvalue);
  6. }
  7. Public Object Get () {
  8. Thread CurrentThread = Thread.CurrentThread ();
  9. //② returns the variable corresponding to this thread
  10. Object o = valuemap.get (CurrentThread);
  11. //③ If it doesn't exist in the map, save it in the map.
  12. if (o = = null &&!valuemap.containskey (CurrentThread)) {
  13. o = InitialValue ();
  14. Valuemap.put (CurrentThread, O);
  15. }
  16. return o;
  17. }
  18. public Void Remove () {
  19. Valuemap.remove (Thread.CurrentThread ());
  20. }
  21. Public Object InitialValue () {
  22. return null;
  23. }
  24. }



Although the threadlocal implementation version in Listing 9 3 looks naïve, it is very similar to the Threadlocal class provided by the JDK in the implementation.

a theadlocal instance

Below, we have a specific example to understand the specific use of threadlocal.

Code Listing 9-4 SequenceNumber

Java code
  1. Package com.baobaotao.basic;
  2. Public class SequenceNumber {
  3. //① Specifies the initial value by overwriting the Threadlocal InitialValue () method with an anonymous inner class
  4. private static threadlocal<integer> SeqNum = new threadlocal<integer> () {
  5. Public Integer InitialValue () {
  6. return 0;
  7. }
  8. };
  9. //② getting the next sequence value
  10. public int Getnextnum () {
  11. Seqnum.set (Seqnum.get () +1);
  12. return Seqnum.get ();
  13. }
  14. public static void Main (string[] args)
  15. {
  16. SequenceNumber sn = new SequenceNumber ();
  17. //③3 a thread to share SN, each generating serial number
  18. testclient T1 = new TestClient (SN);
  19. TestClient t2 = new TestClient (SN);
  20. testclient t3 = new TestClient (SN);
  21. T1.start ();
  22. T2.start ();
  23. T3.start ();
  24. }
  25. private static class TestClient extends Thread
  26. {
  27. private SequenceNumber SN;
  28. Public testclient (SequenceNumber sn) {
  29. this.sn = SN;
  30. }
  31. public Void Run ()
  32. {
  33. //④ 3 sequence values per thread
  34. For (int i = 0; i < 3; i++) {
  35. System.out.println ("thread[" +thread.currentthread (). GetName () +
  36. "] sn[" +sn.getnextnum () +"]");
  37. }
  38. }
  39. }
  40. }



Usually we define the subclass of threadlocal by means of an anonymous inner class, providing the initial value of the variable, as shown in ①. TestClient threads produce a set of serial numbers, and at ③ we generate 3 testclient that share the same SequenceNumber instance. Run the above code and output the following results on the console:

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



Examining the result information of the output, we find that each thread produces an ordinal number that shares the same sequence number instance, but they do not interfere with each other, but instead produce separate serial numbers. This is because we provide a separate copy of each thread through threadlocal.

comparison with thread synchronization mechanism

What are the advantages of threadlocal compared to the thread synchronization mechanism? Both the threadlocal and thread synchronization mechanisms are designed to address the access violation of the same variable in multiple threads.

In the synchronization mechanism, the lock mechanism of the object guarantees that only one thread accesses the variable at the same time. At this time the variable is shared by multiple threads, using the synchronization mechanism requires the program to carefully analyze when to read and write variables, when to lock an object, when to release object locks and other complex problems, programming and writing is relatively difficult.

Threadlocal, however, solves multiple threads of concurrent access from another angle. Threadlocal provides a separate copy of the variable for each thread, isolating multiple threads from conflicting access data. Because each thread has its own copy of the variable, there is no need to synchronize the variable. Threadlocal provides a thread-safe object encapsulation that can encapsulate unsafe variables into threadlocal when writing multithreaded code.

Because the threadlocal can hold any type of object, the Get () provided by the lower version of the JDK returns an object, which requires a type cast. However, JDK 5.0 is a good solution to this problem through generics, to some extent simplifying the use of threadlocal, code listing 9-2 uses the JDK 5.0 new threadlocal<t> version.

To sum up, for multi-threaded resource sharing problem, the synchronization mechanism adopted the "time-to-space" approach: Access serialization, object sharing. The threadlocal uses the "space-for-time" approach: Access parallelization, and the exclusive use of objects. The former provides only one copy of the variable, allowing different threads to queue access, and the latter provides a variable for each thread, so it can be accessed at the same time without affecting each other.

Spring uses threadlocal to resolve thread safety issues

We know that in general, only stateless beans can be shared in a multithreaded environment, and in spring, most beans can be declared as singleton scopes. This is because spring has a "stateful object" of non-thread safety for some beans (such as Requestcontextholder, Transactionsynchronizationmanager, Localecontextholder, etc.) Encapsulation with threadlocal makes them also "stateful objects" that are thread-safe, so stateful beans can work in a singleton manner in multi-threading.

The general Web application divides into the presentation layer, the service layer and the persistence layer three levels, writes the corresponding logic in the different layers, the lower layer through the interface to the upper layer open function calls. In general, all program calls from receiving requests to returning responses belong to one thread, as shown in 9-2.



This allows the user to store some non-thread-safe variables in threadlocal as needed, and the same threadlocal variable accessed by all objects in the same invocation thread of the same request response is bound by the current thread.
The following example can reflect spring's transformation of the stateful bean:

Code Listing 9-5 Topicdao: non-thread safe

Java code
    1. Public class Topicdao {
    2. //① a non-thread-safe variable
    3. private Connection Conn;
    4. public void Addtopic () {
    5. //② referencing non-thread-safe variables
    6. Statement stat = conn.createstatement ();
    7. ...
    8. }
    9. }



Because the conn at ① is a member variable, because the Addtopic () method is non-thread-safe, a new Topicdao instance (not singleton) must be created when it is used. The following uses Threadlocal to transform Conn, a non-thread-safe "state":

Code Listing 9-6 Topicdao: Thread safety

Java code
  1. Import java.sql.Connection;
  2. Import java.sql.Statement;
  3. Public class Topicdao {
  4. //① Saving connection variables using threadlocal
  5. Private static threadlocal<connection> connthreadlocal = new threadlocal<connection> ();
  6. Public static Connection getconnection () {
  7. //② If Connthreadlocal does not have a connection corresponding to this thread to create a new connection,
  8. //And save it in a thread-local variable.
  9. if (connthreadlocal.get () = = null) {
  10. Connection conn = Connectionmanager.getconnection ();
  11. Connthreadlocal.set (conn);
  12. return conn;
  13. }else{
  14. //③ directly returns thread-local variables
  15. return Connthreadlocal.get ();
  16. }
  17. }
  18. public void Addtopic () {
  19. //④ gets the thread corresponding from the threadlocal
  20. Statement stat = getconnection (). createstatement ();
  21. }
  22. }



When using Topicdao, different threads first determine if Connthreadlocal.get () is null, or NULL, indicating that the current thread does not have a corresponding connection object. At this point, a connection object is created and added to the local thread variable, and if it is not NULL, the current thread already has the connection object, which can be used directly. This ensures that different threads use thread-related connection and do not use the connection of other threads. Therefore, this topicdao can be done singleton share.

Of course, this example itself is very rough, put connection threadlocal directly in DAO can only do this DAO's multiple methods sharing connection without thread safety problem, but cannot share the same connection with other DAO, To do the same transaction multiple DAO shares the same connection, you must use Threadlocal to save the connection in a common external class. But this example basically illustrates spring's approach to stateful thread security. Later in this chapter, we'll explain in detail how spring solves the issue of transaction management through Threadlocal.

These articles are excerpted from my "Spring 3.x enterprise Application Development Practice", I will be in the form of a serial, in succession here. You are welcome to discuss

Thread local change, that is, threadlocal-->spring transaction management

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.