Improve scalability (reposted) with threadlocal

xiaoxiao2021-03-06  27

Improve scalability with Threadlocal

The Threadlocal class is quietly appearing in the Java platform version 1.2. While supporting thread part variables is part of many thread tools (such as POSIX PTHREADS tools, the initial design of the Java Threads API does not have this useful feature. Moreover, the initial implementation is also quite inefficient. For these reasons, Threadlocal is very concerned, but it is very convenient to simplify thread security concurrent procedures. In Part 3 of the thread, the Java Software Consultant Brian Goetz studied Threadlocal and provided some skills.

Participate in the Brian multi-thread Java programming discussion forum to get help from threads and concurrency issues in your project.

Write a thread security class is difficult. It not only requires careful analysis of what conditions can read and write variables, but also require careful analysis of how other classes can use a certain class. Sometimes, it is difficult for classes to become thread security without affecting the functions, ease of use, or performance. Some classes reserve status information called from a method to the next method, which is difficult to make such a class a thread security in practice.

Managing Non-threaded security classes is more easier than trying to make classes to become thread security. Non-thread security classes can usually be used safely in multi-threaded programs, as long as you can ensure that the instances of a class used by a thread are not used by other threads. For example, the JDBC Connection class is non-thread security - two threads cannot be safely shared on the small size level. However, if each thread has its own Connection, then multiple threads can safely perform database operations.

It is of course possible to maintain a separate JDBC connection for each thread (or any other object) for each thread; Thread API gives us all the tools you need to connect objects and threads. Threadlocal allows us to easily link threads and its per-thread data.

What is thread local variable (Thread-Local Variable)?

Thread local variables efficiently provide a copy of the single thread partial variable value for each thread using it. Each thread can only see the value associated with you, instead of other threads may be in use or modify their own copy. Some compilers (such as Microsoft Visual C Compiler, or IBM XL Fortran Compiler) use storage class modifiers (like static or volatile) to integrate support for thread local variables into their language. The Java Compiler does not provide special language support for thread local variables; vice versa, it implements these support with Threadlocal classes, and there is special support in the core THREAD class.

Because the thread part variable is implemented by a class, not as part of the Java language itself, the use syntax of the Java language thread local variable is awkward than the use syntax of the inner construction line local variable language. To create a thread local variable, instantiate an object of THREADLOCAL. The behavior of Threadlocal classes is similar to the behavior of various Reference classes in java.lang.ref; the ThreadLocal class acts as a indirect handle that stores or retrieves a value. Listing 1 shows the Threadlocal interface.

Listing 1. Threadlocal interface

Public class threadlocal {

Public Object Get ();

Public void set (Object newValue);

Public Object InitialValue ();

}

GET () Accessor retrieves the value of the current thread of the variable; set () Accessor changes the value of the current thread. The initialvalue () method is optional. If the thread is not used a variable, you can use this method to set the initial value of this variable; it allows delay initialization. Implementing a sample implementation to explain that Threadlocal's work is the best way. Listing 2 shows an implementation of Threadlocal. It is not a particularly good implementation (although it is very similar to the initial implementation), it is very likely that it is poor, but it clearly illustrates Threadlocal's working mode. Listing 2. Threadlocal's bad implementation

Public class threadlocal {

Private Map Values ​​= Collects.SynchronizedMap (New HashMap ());

Public Object get () {

Thread Curthread = thread.currentthread ();

Object o = values.get (Curthread);

IF (o == null&&! value.containskey (curnetread) {

o = initialvalue ();

VALUES.PUT (CURTHREAD, O);

}

Return O;

}

Public void set (Object newValue) {

VALUES.PUT (Thread.currentthread (), NewValue;

}

Public Object InitialValue () {

Return NULL;

}

}

This implementation will not be very good because each get () and set () operations require synchronization on the Values ​​mapping table, and if multiple threads accesses the same Threadlocal, it will occur. In addition, this implementation is not practical because the keywords in the VALUES map table with Thread objects will result in garbage recycling for Thread after threads, and cannot be made to thread-specific values ​​for the thread of Threadlocal of the dead thread. Garbage recycling.

Implement each thread Singleton with threadlocal

Thread local variables are often used to depict shared objects with state "single sub) or thread secure, or by encapsulating unsafe variables into threadlocal, or by putting the object-specific state-specific state into Threadlocal. . For example, in an application that is closely linked to the database, many methods of programs may need access to the database. In each method of the system, it contains a connection as a parameter. It is inconvenient - using "list" to access the connection may be one although more rough, but it is more convenient. However, multiple threads cannot securely share a JDBC Connection. As shown in Listing 3, by using Threadlocal in "单", we can make any classes in our programs to get a reference for each thread Connection. This way, we can think that Threadlocal allows us to create each thread list.

Listing 3. Connect a JDBC to a single thread singleton

Public class connectiondispenser {

Private static class threadlocalconnection extends threadlocal {

Public Object InitialValue () {

Return DriverManager.getConnection (ConfigurationSingleton.getdburl ());

}

}

Private threadlocalconnection conn = new threadlocalConnection ();

Public static connection getConnection () {

Return (Connection) conn.get ();

}

}

Any cost-to-expensive amount of cost is relatively expensive or non-threaded security, such as JDBC Connection or Regular expression matching, is a good place for each thread list. Of course, in this place, you can use other technologies, such as with a pool to securely manage sharing access. However, from the perspective of scalability, there are some potential defects even with pools. Because the pool implementation must use synchronization to maintain the integrity of the pool data structure, if all threads use the same pool, then in systems that are frequently accessed frequently, the program performance will decrease due to dispute.

Simplify debug log records with Threadlocal

Other applications suitable for use Threadlocal but replacement technologies that cannot be good with pools, including storage or accumulation of each thread context information for later retrieval. For example, suppose you want to create a tool for managing multithreaded application debugging information. You can accumulate debugging information as a thread partial container as a thread partial container as a thread. At the beginning of a work unit, you empty the container, and when an error occurs, you query the container to retrieve all the debug information generated by this work unit so far.

Listing 4. Manage each-threaded trial log with Threadlocal

Public class debuglogger {

Private static class threadlocallist extends threadlocal {

Public Object InitialValue () {

Return new arriselist ();

}

Public List getList () {

Return (List) super.get ();

}

}

Private threadlocallist list = new threadlocAllist ();

Private static string [] StringArray = new string [0];

Public void clear () {

List.getlist (). Clear ();

}

Public void Put (String text) {

List.getlist (). Add (text);

}

Public String [] get () {

Return List.getlist (). Toarray (StringArray);

}

}

In your code, you can call DEBUGLGGER.PUT () to save what you are doing, and if necessary (for example, an error happens), you can easily retrieve with a specific thread Related debugging information. With you dump all information to a log file, then try to find out which thread comes from which thread comes from (also worried about the log record object), this technology is much easier and more effective.

ThreadLocal is also useful in any multi-threaded application server based on servlet-based applications or work units because a single thread will be used during the entire process of processing requests. You can store all-request context messages through the threadlocal variables described earlier.

Threadlocal's thread security is a little brother, inheritablethreadlocal

The Threadlocal class has a relative, inheritablethreadlocal, working in a similar way, but applies to applications that are completely different. If you save a thread, if you save the value of all InheritableThreadLocal objects, then these values ​​will also be passed to the sub-thread. If a sub-thread calls incheritablethreadLocal's get (), it will see the same object with its parent thread. To protect thread safety, you should only use InheritableThreadLocal only for non-variable objects (once created, it will never be changed) because the object is shared by multiple threads. InheritableThreadLocal is suitable for transmitting data from the parent threads to sub-threads, such as user IDs, or transaction IDs, but cannot be status objects, such as JDBC Connection. Threadlocal's performance

Although thread part variables have already been famous and included in many thread frames including POSIX PTHReads specification, it is omitted in the initial Java thread design, just add it to the version 1.2 of the Java platform. In many ways, Threadlocal is still in development; it is rewritten in version 1.3, and the version 1.4 has been rewritten once, and it is specifically for performance issues twice.

In JDK 1.2, Threadlocal implementation is very similar to the manner in Listing 2, except for the synchronous weakhashmap instead of HashMap to store VALUES. (At the expense of some extra performance overhead, using WeakhashMap solves the problem that the THREAD objects that cannot be garbage-collecting the Thread object cannot be said.) Don't say, Threadlocal's performance is quite worse.

The Threadlocal version provided by the Java platform version 1.3 has been as better as possible; it does not use any synchronization, so there is no scalability problem, and it does not use weak references. Conversely, people have modified the Threadlocal by adding an instance variable to thread (this variable is used to save the "HashMap from the thread local variable to its mapping) to support Threadlocal. Because the process of retrieving or setting a thread local variable does not involve reading and writing of data that may be read or written by another thread, you can implement threadlocal.get () and set () without any synchronization. Moreover, since each thread value is stored in the own Thread object, it is also possible to garbage collection when garbage recovery is used for Thread.

Unfortunately, even if these improvements, the performance of Threadlocal in Java 1.3 is still surprisingly slow. According to my rough measurement, THREADLOCAL.GET () operations are performed in the Sun 1.3 JDK on the Dual processor Linux system, and the time consuming is about twice the same. The reason why the performance is the thread.currentthread () method is very large, accounting for two-thirds of the threadlocal.get () run time. Although there are these shortcomings, JDK 1.3 threadlocal.get () is still much more faster than the contention, so if there is any serious disputeless place (maybe there are very many threads, or synchronized blocks are frequently performed, or synchronized The block is large), Threadlocal may still be much efficient.

In the latest version of the Java platform, that is, version 1.4b2, Threadlocal and Thread.currentthread () have greatly improved. With these improvements, Threadlocal should be more faster than other techniques, such as pool. Since it is simpler than other technologies, it is more difficult to mistake, and people will eventually find an effective way to avoid undesirable interactions between threads. The benefits of threadlocal

Threadlocal can bring a lot of benefits. It is often used to depict state classes to thread, or encapsulate non-threaded security classes to securely use the easiest way to safely use in multithreaded environments. Using Threadlocal allows us to bypass when to implement thread security, it needs to be synchronized, and scalability is also improved because it does not need any synchronization. In addition to simplicity, use Threadlocal storage per-thread or each thread context information in archiving in terms of archiving - by using ThreadLocal, the object stored in Threadlocal is unclear, thus simplifying Judging whether a class is working safely.

I hope that you have been having fun from this series, and I have learned knowledge. I also encourage you to go to my discussion forum to study multithreaded problems.

About author

Brian Goetz is a software consultant that has been professional software developers in the past 15 years. He is the Chief Consultant of Quiotix, which is engaged in software development and consultation, located in Los Altos, California. Please check the list of papers that Brian has published and will be published in popular industry publications. Can contact Brian via brian@quiotix.com.

转载请注明原文地址:https://www.9cbs.com/read-65200.html

New Post(0)