Introduction
In a blink of an eye has not written more than two years of blog, a blink of an eye also to work fast for two or three year, in a blink of an eye I began to write Java code again. Hope that they can persist in writing blog, summarize the habit of summing up! Come on.
Today, when debugging the code, it was strange to find two unrelated threads using Jstack to see if one of the locks was waiting for another thread to hold. The research is due to the implementation mechanism of the integer class.
One, the exception block code
1 Packagexxx;2 3 Public classTestdeadlock {4 Public Static voidMain (string[] Argvs) {5 6 NewA ("Threada"). Start ();7 NewB ("Threadb"). Start ();8 Try {9Thread.Sleep (15000);Ten}Catch(Exception e) { One A } - } - } the classAextendsThread { - PublicA (String name) {Super(name);} - Private FinalObject Updatelock = 0; - @Override + Public voidrun () { - System.out.println (Updatelock.getclass ()); + synchronized(updatelock) { ASystem.out.println (System.currenttimemillis () + "in A"); at Try { -Sleep (100000); -}Catch(interruptedexception e) { - - } - } in } - } to classBextendsThread { + PublicB (String name) {Super(name);} - Private FinalObject Updatelock = 0; the @Override * Public voidrun () { $ System.out.println (Updatelock.getclass ());Panax Notoginseng synchronized(updatelock) { -System.out.println (System.currenttimemillis () + "in B"); the Try { +Sleep (100000); A}Catch(interruptedexception e) { the + } - } $ } $}
The above code is very simple, set up two threads, print a word, each thread has a local variable updatelock used to synchronize within its own thread. The problem is on the updatelock. Running the above code will find that the two threads will block each other, updatelock the internal objects of the thread, why do they block each other? The problem arises in the 17 and 33 rows of the 0 assignment. 0 The value itself is a primitive type int,updatelock is a type of object, because it actually assigns the 0 to the integer type to the Updatelock object, so how does this work inside Java? This assignment is implemented by the ValueOf method that relies on the integer.
Second, the valueof realization of integer
1 public static Integer valueOf (int i) { 2 if (i >= integercache.low && i <= Integercache.high) 3 return integercache.cache[i + (-integercache.low)]; 4 return New Integer (i); 5 }
You can see that the implementation of valueof depends on the implementation of Integercache, from the name can be seen Integercache is a interger cache, Integercache cache this from 128 to 127 ( The upper limit of 127 can be modified through the JVM configuration). The logic of valueof is that if there is a cache, the cache is returned, and a new integer object is returned without being present.
Third, the realization of Integercache
1 Private Static classIntegercache {2 Static Final intLow =-128;3 Static Final intHigh ;4 Static FinalInteger cache[];5 6 Static {7 //High value is configured by property8 intH = 127;9String Integercachehighpropvalue =TenSun.misc.VM.getSavedProperty ("Java.lang.Integer.IntegerCache.high"); One if(Integercachehighpropvalue! =NULL) { A Try { - inti =parseint (integercachehighpropvalue); -i = Math.max (i, 127); the //Maximum array size is Integer.max_value -h = math.min (i, Integer.max_value-(-low)-1); -}Catch(NumberFormatException nfe) { - //If The property cannot is parsed into an int, ignore it. + } - } +High =h; A atCache =Newinteger[(high-low) + 1]; - intj =Low ; - for(intk = 0; K < Cache.length; k++) -CACHE[K] =NewInteger (j + +); - - //range [ -128, 127] must be interned (JLS7 5.1.7) in assertIntegercache.high >= 127; - } to + PrivateIntegercache () {} -}
The implementation of Integercache is relatively simple, in fact, is the internal maintenance of a cache array, in advance new good object, need to return directly, no longer create objects, because the cost of creating objects is very high, this can improve efficiency. The interesting thing about this is that the JVM needs to modify the cache cache's upper limit through the Java.lang.Integer.IntegerCache.high configuration, but it does not provide a configuration to modify the lower bound, and it is not known what the purpose of this is, yet to be explored.
Four, in-depth object updatelock = 0
Because the amount of code in the first section creates a problem with threads blocking each other, you can guess that updatelock in two threads is actually the same object, that is, updatelock in two threads is two identical integer objects. The same integer object is likely to be the object returned by the ValueOf method that produced the integer. To verify our conjecture, we break the breakpoint to Java.lang.Interger's valueof function to debug and look at the call stack, as shown in
The above figure validates our conjecture. So how to solve this problem is very simple. You can assign a new Object () to Updatelock.
Summarize
If an object is intended to be synchronized after the Synchronized keyword, then an int or other intrinsic type assignment is not allowed, as in the example code in the first section, the standard practice should be as follows
Final New Object ();
One-time thread exception-blocking tour due to Java memory management mechanism