Thread synchronization and threadlocal-free thread closure implementation in Java _java

Source: Internet
Author: User
Tags class definition closure manage connection object object rollback thread class

Synchronized keyword

A keyword in the Java language that, when used to modify a method or a block of code, ensures that at most one thread at the same time executes that segment of code.

When two concurrent threads access the synchronized (this) synchronized code block in the same object, only one thread can be executed at a time. Another thread must wait until the current thread finishes executing the code block before executing the code block.
However, when one thread accesses a synchronized (this) synchronization code block of object, another thread can still access a synchronized (this) synchronization code block in that object.
In particular, when a thread accesses a synchronized (this) synchronized code block of object, access to all other synchronized (this) synchronized blocks in object is blocked by another thread.
The third example also applies to other synchronized code blocks. That is, when a thread accesses a synchronized (this) synchronization code block of object, it obtains the object lock of the objects. As a result, access to all of the synchronization code portions of the object object by other threads is temporarily blocked.
The rules above apply to other object locks as well.
code example

Package test160118;
    public class Testsynchronized {public static void main (string[] args) {sy sy = new Sy (0);
    Sy sy2 = new Sy (1);
    Sy.start ();
  Sy2.start ();

  } class Sy extends Thread {private int flag;
  static Object x1 = new Object ();

  static Object x2 = new Object ();
  Public Sy (int flag) {This.flag = flag;
    @Override public void Run () {SYSTEM.OUT.PRINTLN (flag);
          try {if (flag = 0) {synchronized (x1) {System.out.println (flag+ "locked X1");
          Thread.Sleep (1000);
          Synchronized (x2) {System.out.println (flag+ "locked X2");
        } System.out.println (flag+ "released X1 and X2");
          } if (flag = 1) {synchronized (x2) {System.out.println (flag+ "locked X2");
          Thread.Sleep (1000);
          Synchronized (x1) {System.out.println (flag+ "locked X1");
        } System.out.println (flag+ "released X1 and X2"); catch (InterRuptedexception e) {e.printstacktrace ();

 }
  }
}


implementation principle of threadlocal thread closure without locking
What can threadlocal do?

This is not a good word to say, we might as well look at the actual project encountered some of the difficult solutions: when you enter a method in a project based on some parameter calls, and then the method calls the method, and then invokes the method across the object, many levels, these methods may use some similar parameters, for example, a in the need for parameters A, B, C, A after calling B, B and C parameters are required, and B called C method requires a, B parameters, at this time have to pass all the parameters to B, and so on, if there are many methods of call, at this time the parameters will become more and more complex, in addition, when the program needs to add parameters, at this time need to add parameters to the relevant methods Yes, very troublesome, I believe you have encountered, this is also in the C language object-oriented some common processing means, but our simple approach is to wrap it into objects passed in, by adding the object's properties can solve the problem, but the object is usually meaningful, So sometimes a simple object wrapper adds some extended unrelated attributes that make our class definition very strange, so in these cases when we're architecting this kind of complex program, we handle it by using a class that resembles scope, and the name and use are more generic, Similar Web applications will have context, session, request, page level scope, and threadlocal can solve such problems, but he is not very suitable to solve such problems, It faces these problems are usually initially not in accordance with the scope and the way the object passed, that will not increase the parameters, when adding parameters, found to change a lot of places, in order not to break the structure of the code, there may be too many parameters, has made the code of the method less readable, Add threadlocal to deal with, for example, one method calls another method to pass in 8 parameters, through the layer call to the Nth method, passed one of the parameters, this time the last method needs to add a parameter, the first method to 9 parameters is natural, but this time, Related methods can be implicated, making the code bloated.

The above mentioned threadlocal a kind of remedial use, but it is not a particularly recommended way, it has some similar ways to use, that is, at the framework level there are many dynamic calls, the call process needs to meet some protocol, although the Protocol we will try to general, While many of the extended parameters are not easy to consider when defining the protocol, and the version is also at any time in the upgrade, but when the framework is extended to meet the universality of the interface and backward-compatible, and some of the expanded content we need to threadlocal to facilitate simple support.

In short, threadlocal is a simple definition of some complex system extensions, making the part of the associated parameters very easy, and here is our example:

In spring's transaction manager, the connection of the data source is placed in the threadlocal, and the program is executed by the threadlocal to obtain connection and then commit and rollback, in use, To make sure that the program gets it through the DataSource connection is taken from spring, why do you do this because the business code is entirely up to the application and the framework does not require the business code to write, Otherwise, you lose the framework. The benefits of not letting business code manage connection, when the business code is cut into, spring does not pass in a connection to the business code area, which must be kept in one place when the underlying passes through the Ibatis, spring When a framework such as JDBC acquires the same datasource connection, it invokes the rules to be obtained according to the spring conventions, because the execution process is handled in the same thread to obtain the same connection to ensure that the commit, Rollback and the business operation process, the use of connection is the same, because only the same Conneciton can guarantee transactions, otherwise the database itself is not supported.

In fact, in many concurrent programming applications, Threadlocal plays a very important important, it does not lock, very easy to close the thread is seamless, and will not like local variables each need to new allocation of space, a lot of space because it is thread-safe, so you can reuse the thread-private buffer.

How to use threadlocal?

Define a ThreadLocal variable in any suitable location in the system, defined as a public static type (directly new to a ThreadLocal object), to put data into it using Set (object), to get the data to use the fetch () Action, delete the element with remove (), the rest of the method is not public method, do not recommend the use.

The following is a simple example (code fragment 1):

 public class ThreadLocalTest2 {public final static ThreadLocal <string>test_thr

 ead_name_local = new threadlocal<string> ();

 Public final static ThreadLocal <string>test_thread_value_local = new threadlocal<string> ();
  public static void Main (String[]args) {for (int i = 0; i < i++) {final String name = "Thread-" "+ i +" "";
  Final String value = string.valueof (i);
   New Thread () {public void run () {try {test_thread_name_local.set (NAME);
   Test_thread_value_local.set (VALUE);
   Calla ();
   }finally {test_thread_name_local.remove ();
   Test_thread_value_local.remove ();
 }}.start ();
 }} public static void Calla () {callb ();
 public static void Callb () {new ThreadLocalTest2 (). CALLC ();
 public void Callc () {CallD ();
 public void CallD () {System.out.println (Test_thread_name_local.get () + "/t=/t" + test_thread_value_local.get ()); }
}

Here simulate 100 threads to access to set the name and value respectively, the middle deliberately set the value of name and value to the same, see if there is a concurrency problem, through the output can be seen, the thread output is not in order output, the description is executed in parallel, and thread name and value is can correspond to, in the middle through the invocation of multiple methods, in the form of the actual call of the parameters do not pass, how to obtain the corresponding variable process, but the actual system will often cross classes, here only in a class simulation, in fact, cross class is the same result, we can simulate on their own.

Believe that see here, a lot of programmers are interested in the principle of ThreadLocal, see how it is done, the parameters do not pass, but also as local variables like to use it, it is quite magical, in fact, to see what is a way to set up, see the name should be and thread related, So cut the crap, take a look at its source code, since we use the most is set, get and remove, then start with set:

Set (T obj) method is (code fragment 2):

public void Set (t value) {
 Thread t = thread.currentthread ();
 Threadlocalmap map = getmap (t);
 if (map!= null)
 Map.set (this, value);
 else
 createmap (t, value);

First get the current thread, and guess the same, and then there is a Getmap method, passed in the current thread, we can first understand that the map is a thread-related map, then if not empty, do set operation, you trace in to find that this is similar to the HashMap put operation, That is, write a piece of data to the map, and if it is empty, call the Createmap method and go inside and see (Code fragment 3):

void Createmap (Thread T, T firstvalue) {
 t.threadlocals = new Threadlocalmap (this, firstvalue);

A threadlocalmap is created, and the incoming arguments and current threadlocal are written as k-v structures (code fragment 4):

Threadlocalmap (ThreadLocal Firstkey, Object firstvalue) {
 table = new Entry[initial_capacity];
 int i = Firstkey.threadlocalhashcode & (initial_capacity-1);
 Table[i] = new Entry (Firstkey, firstvalue);
 size = 1;
 Setthreshold (initial_capacity);
}

This does not explain the structure of the threadlocalmap, just know that its implementation and HashMap similar, but many methods do not, and do not implements map, because it does not want you in some way (such as reflection) to get a map to the further operation of him, It is a static inner class inside a threadlocal, the default type, just below the Java.lang class can refer to it, so you can think of thread can refer to it.

Let's go back and look at the Getmap method, because I just know that the map being retrieved is thread-related, and by code fragment 3, there is a t.threadlocalmap = new Threadlocalmap (this, firstvalue), I believe you should probably understand that this variable should come from thread, and we'll look at it according to the Getmap method:

Threadlocalmap Getmap (Thread t) {return
 t.threadlocals;
}

Yes, it comes from thread, and this thread is just the current one, so go in and see what the definition is:

Threadlocal.threadlocalmap threadlocals = null;

This property is in the thread class, where each thread defaults to a threadlocalmap that holds the thread-level local variables, and usually you can't assign values to them because such assignments are usually unsafe.

Seems to be not a bit messy, not anxious, we look back to explore the next train of thought:

1, thread has a property is similar to the hashmap thing, but its name is Threadlocalmap, this property is the default type, so the same package all the following classes can be referenced, because is the thread of the local variable , so each thread has a separate map of its own that does not conflict with each other, so there is no conflict between defining threadlocal as a static thread.

2, threadlocal and thread are under the same package, you can refer to this class, you can do the operation, at this time threadlocal each defined one, with this as key, the value you passed in as value, And this is the threadlocal you define, so different threadlocal variables, all use set, the data between each other will not conflict, because their key is different, of course, the same threadlocal do two times set operation, will be the last time to prevail.

3. To sum up, parallel between threads, threadlocal can be used as local variables and thread-safe, and the data between different threadlocal variables is not conflicting.

We continue to look at the Get method and the Remove method, which is actually simple:

Public T get () {
 Thread t = thread.currentthread ();
 Threadlocalmap map = getmap (t);
 if (map!= null) {
 Threadlocalmap.entry e = Map.getentry (this);
 if (e!= null) return
  (T) e.value;
 }
 return Setinitialvalue ();
}

By invoking the Getmap method based on the current thread, That is, call the T.threadlocalmap and look in the map, and notice that the map finds the entry, the K-V basic structure, because you write only a value, so it sets a e.value to return the value you write, because the key is the threadlocal itself. You can see that map.getentry is also obtained through this.

The same remove method is:

public void Remove () {
 Threadlocalmap m = Getmap (Thread.CurrentThread ());
 if (M!= null)
  m.remove (this);
}

The map is also obtained from the current thread, and if not empty, remove, through this.

Add (2013-6-29), forget to write what pit, this threadlocal have what pit, you should be able to see from the front, this threadlocal related object is bound to a map, and this map is a thread in the threads of a property, Then there is the problem that if you do not remove it or if you do not know when to remove it in your own program, the thread does not log off, and the data that is set in will not be logged out.

Conversely, in writing code unless you have a clear understanding of where the object should be set, where remove, and if it is blurry, it is likely that your code will not take the location of the remove, or cause some logic problems, and, if not remove, you should wait for the thread to log off, We are in many application servers, threads are reused because there is still overhead in allocating threads to the kernel, so it's hard to write down the data in these applications because it's not easy to log off, and these may be inadvertently hidden when we use certain open source frameworks, which can be used in a threadlocal. , it is possible to cause problems, and finally found that oom data from the Threadlocalmap, do not know where the data is set from, so you should pay attention to this pit, probably more than one person fell into the pit.

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.