Provides a thorough understanding of threadlocal to implement secure multithreading.

Source: Internet
Author: User

We know that spring makes it easier for developers to use various data persistence technologies through various Dao template classes. These template classes are thread-safe, that is, multiple Dao can reuse the same template instance without conflict.

We use the template class to access the underlying data. Based on the persistence technology, the template class needs to bind resources for data connections or sessions. However, these resources are non-thread-safe, that is, they cannot be shared by multiple threads at the same time.

Although the template class acquires data connections or sessions through the resource pool, the resource pool solves the cache issue of data connections or sessions, not the thread security issue of data connections or sessions.

According to traditional experience, if an object is non-thread-safe, in a multi-threaded environment, the access to the object must use synchronized for thread synchronization. However, the DaO template class in spring does not adopt the thread synchronization mechanism, because thread synchronization limits concurrent access, which will cause great performance loss.

In addition, it is very challenging to solve the performance security problem through code synchronization, which may increase the implementation difficulty several times. What kind of magic does the template class admire? Can we solve the thread security problem without synchronization? The answer is threadlocal!

Threadlocal plays an important role in spring. It has appeared in bean, transaction management, task scheduling, AOP and other modules that manage Request scopes, and plays an important role. To understand the underlying technology of Spring transaction management, threadlocal is a mountain fortress that must be overcome.

What is threadlocal?

As early as JDK 1.2, java. Lang. threadlocal is provided. threadlocal provides a new way of thinking to solve the concurrent problem of multi-threaded programs. Using this tool class, you can easily compile beautiful multi-threaded programs.

Threadlocal is easy to understand and take for granted as a "local thread ". In fact, threadlocal is not a thread, but a local variable of the thread. It may be easier to understand to name it threadlocalvariable.

When threadlocal is used to maintain a variable, threadlocal provides an independent copy of the variable for each thread that uses the variable. Therefore, each thread can change its own copy independently, it does not affect the copies corresponding to other threads.

From the thread perspective, the target variable is like the local variable of the thread, which is also the meaning of "local" in the class name.

Thread Local variables are not new to Java. Many languages (such as ibm xl Fortran) provide thread local variables at the syntax level. Java does not provide language-level support, but uses threadlocal classes in disguise.

Therefore, the code for writing thread local variables in Java is relatively clumsy, so thread local variables are not widely used by Java developers.

Threadlocal Interface Method

Threadlocal class interface is very simple. There are only four methods. Let's take a look at it first:

  • Void set (object value)

Set the value of the local variable of the current thread.

  • Public object get ()

This method returns the local variable of the thread corresponding to the current thread.

  • Public void remove ()

Delete the local variable value of the current thread to reduce memory usage. This method is 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.

It is worth mentioning that in jdk5.0, threadlocal already supports generics, and the class name of this class has changed to threadlocal <t>. API method
The new API methods are also adjusted accordingly. The new API methods are void set (T value), t get (), and T initialvalue ().

How does threadlocal maintain copies of variables for each thread? In fact, the implementation idea is very simple: there is a map in the threadlocal class, which is used to store a copy of the variable of each thread. The key of 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:

// Code List 1 simplethreadlocal

Class simplethreadlocal {
Private map valuemap = collections. synchronizedmap (New hashmap ());
Public void set (Object newvalue ){
Valuemap. Put (thread. currentthread (), newvalue); // ① the key is the thread object, and the value is a copy of the variable of the thread
}
Public object get (){
Thread currentthread = thread. currentthread ();
Object o = valuemap. Get (currentthread); // ② return the variable corresponding to this thread
If (O = NULL &&! Valuemap. containskey (currentthread) {// ③ if it does not exist in map, put it in Map
.
O = initialvalue ();
Valuemap. Put (currentthread, O );
}
Return O;
}
Public void remove (){
Valuemap. Remove (thread. currentthread ());
}
Public object initialvalue (){
Return NULL;
}
}

Although the threadlocal implementation version of code listing 9 listing 3 seems naive, it is similar to the threadlocal class provided by JDK in terms of implementation ideas.

A theadlocal instance

Next, let's take a look at the specific usage of threadlocal through a specific instance.

Package threadlocaldemo;

Public class sequencenumber {
// ① Overwrite the initialvalue () method of threadlocal through an anonymous internal class and specify the Initial Value
Private Static threadlocal <integer> seqnum = new threadlocal <integer> (){
Public integer initialvalue (){
Return 0;
}
};
// ② Obtain the next Sequence Value
Public int getnextnum (){
Seqnum. Set (seqnum. Get () + 1 );
Return seqnum. Get ();
}
Public static void main (string [] ARGs)
{
Sequencenumber Sn = new sequencenumber ();
// ③ Three threads share the SN, each generating a serial number
Testclient T1 = new testclient (SN );
Testclient t2 = new testclient (SN );
Testclient T3 = new testclient (SN );
T1.start ();
T2.start ();
T3.start ();
}
Private Static class testclient extends thread
{
Private sequencenumber Sn;

Public testclient (sequencenumber Sn ){
This. Sn = Sn;
}
Public void run ()
{
For (INT I = 0; I <3; I ++ ){
// ④ Each thread generates three sequence values
System. Out. println ("thread [" + thread. currentthread (). getname () + "] Sn [" + SN. getnextnum () + "]");
}
}
}
}

We usually define threadlocal subclass by using an anonymous internal class to provide the initial variable value, as shown in example ①. The testclient thread generates a set of serial numbers,
At ③, we generate three testclients that share the same sequencenumber instance. Run the above Code and output the following results on the console:

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]

Test the output result information. We find that although the serial numbers generated by each thread share the same sequencenumber instance, they do not interfere with each other, but each generates independent serial numbers, this is because we provide separate copies for each thread through threadlocal.

Comparison of thread synchronization mechanisms

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.
Data access conflict. Because every thread has its own copy of the variable, there is no need to synchronize the variable. Threadlocal provides thread-safe shared objects.
When writing multi-threaded code, you can encapsulate insecure variables into threadlocal.

Because threadlocal can hold any type of objects, get () provided by JDK of lower versions returns object objects and requires forced type conversion. However, JDK
5.0 solve this problem through generics. To a certain extent, the use of threadlocal is simplified, and JDK is used in Code List 9 2.
5.0 new threadlocal <t> version.

To sum up, for multi-threaded resource sharing, the synchronization mechanism adopts the "Time for space" approach, while threadlocal adopts the "space for Time" approach. 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.

Spring uses threadlocal to solve thread security problems

We know that in general, only stateless beans can be shared in multi-threaded environments. In spring, most beans can be declared as Singleton.
Domain. It is because Spring has some beans (such as requestcontextholder,
Transactionsynchronizationmanager, localecontextholder, etc.) Non-thread security status
Threadlocal is processed to make them thread-safe, because stateful beans can be shared in multiple threads.

Generally, web applications are divided into three layers: presentation layer, service layer, and persistence layer. The corresponding logic is written in different layers. The lower layer opens function calls through interfaces to the upper layer. In general, all program calls from receiving a request to returning a response belong to the same thread, as shown in figure 9:

Figure 1 three layers of a thread

In this way, you can store non-thread-safe variables as threadlocal as needed. In the call thread of the same request response, all associated Objects Reference the same variable.

The following example shows how spring modifies stateful beans:

Code List 3 topicdao: Non-thread security

Public class topicdao {

Private connection conn;A non-thread-safe variable

Public void addtopic (){

Statement stat = conn. createstatement ();Reference non-thread security variables

...

}

}

Because the conn at ① Is a member variable, because the addtopic () method is non-thread-safe, you must create a new topicdao instance (not Singleton) when using it ). The following uses threadlocal to transform the non-thread-safe state of Conn:

Code list 4 topicdao: thread security

Package threadlocaldemo;

Import java. SQL. connection;
Import java. SQL. sqlexception;
Import java. SQL. statement;

Public class sqlconnection {
// ① Use threadlocal to save the connection variable
Private Static threadlocal <connection> connthreadlocal = new threadlocal <connection> ();
Public static connection getconnection (){
// ② If connthreadlocal does not have the connection corresponding to this thread to create a new connection,
// And save it to the local variable of the thread.
If (connthreadlocal. Get () = NULL ){
Connection conn = getconnection ();
Connthreadlocal. Set (conn );
Return conn;
} Else {
Return connthreadlocal. Get ();
// ③ Directly return the local variable of the thread
}
}
Public void addtopic (){
// ④ Obtain the connection corresponding to the thread from threadlocal
Try {
Statement stat = getconnection (). createstatement ();
} Catch (sqlexception e ){
E. printstacktrace ();
}
}
}

When using topicdao, different threads first determine whether connthreadlocal. Get () is null. If it is null, it indicates that the current thread has no
Create a connection object and add it to the local thread variable. If it is not null, it indicates that the current thread already has
Connection object. This ensures that different threads Use thread-related connections instead of other threads.
Connection. Therefore, this topicdao can be shared by Singleton.

Of course, this example is very rough. If you put the threadlocal of connection directly in Dao, you can only share the connection with multiple methods of the Dao.
There is no thread security problem, but it cannot share the same connection with other Dao. To share the same connection with multiple Dao in the same transaction, it must be in a common external class.
Use threadlocal to save the connection. However, this example basically illustrates spring's solution to stateful thread security.

Summary

Threadlocal is a good idea to solve the thread security problem. It solves the conflict of variable concurrent access by providing an independent variable copy for each thread. In many cases
Threadlocal is simpler and more convenient than using the synchronized synchronization mechanism to solve thread security problems, and the result program has a higher concurrency.

(Reproduced to http://www.builder.com.cn/2007/0529/404695.shtml)

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.