Enhancements to CAS in Java 8

Source: Internet
Author: User
Tags cas

A few days ago, I accidentally wrote previously written to test Atomicinteger and synchronized self-enhanced performance code ran a bit, unexpectedly found Atomicinteger performance than synchronized better, after some reason to find, with the following findings:

In jdk1.7, the getandincrement of Atomicinteger is this:

public final int getandincrement () {for (;;) {int current = Get (); int next = current + 1; if (Compareandset (current, next)) return current;} public final boolean compareandset ( int expect, int update) {return Unsafe.compareandswapint (this, Valueoffset, expect, update);}      

And in jdk1.8, this is the case:

Getandincrementreturn Unsafe.getandaddint (1);} 

It can be seen that in jdk1.8, the Getandaddint method of unsafe is used directly, but in jdk1.7 unsafe, there is no such method. (PS: In order to find out the reason, I decompile the unsafe, found that the CAS failed retry is done in the Getandaddint method, I use reflection to get to the unsafe instance, write the same code as Getandaddint, But the test results are as slow as jdk1.7 's getandincrement, do not know what the unsafe inside what the black magic, but also please the expert generous advice) (supplement: article at the end of the inference)

By looking at the source code of Atomicinteger can be found, affected by the Getandadd, Addandget and other methods.

With this enhancement to CAS, we have one more reason to use non-blocking algorithms.

Finally give the test code, it should be noted that this test method is simple and rough, compareandset performance is not as good as synchronized, and can not simply say synchronized is better, the use of the two are different, and in actual use, there is business processing, There can be no such high competitive strength, this comparison is only a reference, and the test proves that the performance of atomicinteger.getandincrement has improved significantly.

Package performance;Import Java.util.concurrent.CountDownLatch;Import Java.util.concurrent.atomic.AtomicInteger;Import Java.util.concurrent.locks.LockSupport;PublicClassatomictest {Test scale, call once getandincreasex to provide a business service to record the time-consuming of providing test_size servicesPrivateStaticFinalint test_size =100000000;Number of client threadsPrivateStaticFinalint thread_count =10;Use Countdownlatch to let threads start at the same timePrivate Countdownlatch CDL =New Countdownlatch (Thread_count +1);Privateint n =0;Private Atomicinteger AI =New Atomicinteger (0);PrivateLong StartTime;PublicvoidInit() {startTime = System.nanotime ();}/** * with atomicinteger.getandincrement, the test result is 1.8:1.7 significant performance improvement *@return */PrivateFinalIntGetandincreasea() {int result = Ai.getandincrement ();if (result = = Test_size) {System.out.println (System.nanotime ()-startTime); System.exit (0);}return result;}/** * Using synchronized to complete synchronization, test results of 1.7 and 1.8 almost no performance difference *@return */PrivateFinalIntGetandincreaseb() {int result;Synchronized (This) {result = n++;}if (result = = Test_size) {System.out.println (System.nanotime ()-startTime); System.exit (0);}return result;}/** * Use Atomicinteger.compareandset to do a failure retry at the Java code level (similar to the implementation of the 1.7 atomicinteger.getandincrement), * test results of 1.7 and 1.8 almost no performance difference *@return */PrivateFinalIntGetandincreasec() {int Result;do {result = Ai.get ();}while (!ai.compareandset (result, result +1));if (result = = Test_size) {System.out.println (System.nanotime ()-startTime); System.exit (0);}return result;}PublicClassMyTaskImplementsRunnable {@OverridePublicvoidRun() {Cdl.countdown ();try {cdl.await ();} catch (interruptedexception e) {e.printstacktrace ();} while (true) Getandincreasea ();  Getandincreaseb ();}} public static void main (string[] args) throws interruptedexception {atomictest at = new AtomicTest (); for (int n = 0; n < THREAD_COUNT; n + +) new Thread (at.new mytask ()). Start (); System.out.println ( "start"); At.init (); At.cdl.countDown ();}}      

The following are the test results under the Intel (R) Core (TM) I7-4710HQ CPU @2.50ghz (quad core Eight thread) (less volatile, so each item is tested only four or five times, whichever is the more intermediate value):

jdk1.7

Atomicinteger.getandincrement 12,653,757,034
Synchronized 4,146,813,462
Atomicinteger.compareandset 12,952,821,234

jdk1.8

Atomicinteger.getandincrement 2,159,486,620
Synchronized 4,067,309,911
Atomicinteger.compareandset 12,893,188,541

Supplement: At the request of the Netizen, here provide the relevant source code of Unsafe.getandaddint and my test codes.

Use Jad to decompile the source code obtained from unsafe jdk1.8:

PublicFinalIntGetandaddint(Object obj,long L, int i) {int j; Do j = Getintvolatile (obj, L); while (!compareandswapint (obj, L, J, J + i)); return J;} public native int getintvolatile (Object obj, long l); public final native boolean compareandswapint (Object obj, long L, int I, int j);               

OPENJDK8 's unsafe source code:

PublicFinalIntGetandaddint(Object O,Long offset,int Delta) {int v; do {v = getintvolatile (o, offset);} while (!compareandswapint (o, offset, V, v + delta)); return V;} public native int getintvolatile (Object O, long offset); public final native boolean compareandswapint (Object O, long offset, int expected, int x);               

My test code (hint: if the eclipse and other IDE error, it is because the use of restricted unsafe, you can reduce the warning level from error to warning, specific Baidu can be):

... import sun.misc.Unsafe;PublicClassAtomictest {....Private UnsafeUnsafePrivateLong Valueoffset;PublicAtomictest () {Field F;try {f = Unsafe.class.getDeclaredField ("Theunsafe"); F.setaccessible (true);unsafe = (unsafe) F.GetNULL); Valueoffset =unsafe.objectfieldoffset (AtomicInteger.class.getDeclaredField ( catch (nosuchfieldexception e) {...}} private final int getandincreased (int result; Do{result = unsafe.getintvolatile (AI, valueoffset);} while (! Unsafe.compareandswapint (AI, valueoffset, result, Result+1)); if (result = = MAX) {system.0);} return result; ...} 

Add 2: For performance improvement reasons, there are the following inferences, although not to say absolutely correct (because there is no use of the JVM source as an argument), but still have a great grasp of, thanks netizens @ Zhou and @liuxinglanyue!

Unsafe is specially handled and cannot be understood as a regular Java code, except that:

When calling Getandaddint, if the system support Fetch-and-add, then it executes native method, using Fetch-and-add;
If not, follow the Getandaddint method as seen above, in the way of Java code to execute, using the Compare-and-swap;

This also coincides with the note above the Unsafe::getandaddint in Openjdk8:

The following contain cas-based Java implementations used on//platforms not supporting native instructions

The special handling of unsafe is the "black magic" that I referred to above.

RELATED links:

Http://ashkrit.blogspot.com/2014/02/atomicinteger-java-7-vs-java-8.html
Http://hg.openjdk.java.net/jdk8u/hs-dev/jdk/file/a006fa0a9e8f/src/share/classes/sun/misc/Unsafe.java

Enhancements to CAS in Java 8

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.