The great God takes you to Know "CAS in JAVA" __java

Source: Internet
Author: User
Tags cas visibility volatile timedelta

CAS is a modern operating system, to solve the problem of concurrency is an important means, recently in the Eureka to see the source code. Many CAS operations were encountered. Today we will review the CAs in Java in a systematic way.

Read this article and you will learn:

What is CAS

What the CAS implementation principle is.

The application of CAS in reality

Spin lock

Atomic type

Current limiting device

The disadvantages of CAs what are CAS

CAS: Full name compare and swap, literal: compare and swap, a CAS involves the following operations:

We assume that the original data in memory V, the old expected value A, needs to be modified by the new value B.

Compare A and V for equality. Comparison

If the comparison is equal, write B to V. Exchange

Returns whether the operation was successful.

When multiple threads perform a CAS operation on a resource at the same time, only one thread succeeds, but it does not block other threads, and other threads only receive a signal that the operation failed. Visible CAS is actually an optimistic lock. how CAS is implemented

Follow the Atominteger code we go down, we can find the final call is Sum.misc.Unsafe this class. Look at the name Unsafe is an unsafe class, which utilizes Java classes and packages in the visibility of the rules of a right place in the hole. Unsafe This class makes a certain compromise on the Java security standards for speed.

And looking down, we found that the compareandswapint of unsafe is Native:

Public Final native Boolean compareandswapint (Object var1, long var2, int var4, int var5);

In other words, these CAS methods should be using a local method. So the specific implementation of these methods requires us to go to the JDK's source code search.

So I downloaded a OPENJDK source code to continue to explore, we found that in the/jdk9u/hotspot/src/share/vm/unsafe.cpp there are such codes:

{CC "Compareandsetint", CC "(" OBJ "J" "I" "I" ") Z", Fn_ptr (Unsafe_compareandsetint)},

This involves, JNI calls, interested students can learn by themselves. After searching for unsafe_compareandsetint, we found:

Unsafe_entry (Jboolean, Unsafe_compareandsetint (jnienv *env, Jobject UNSAFE, jobject obj, jlong offset, jint E, Jint x)) {   OOP p = jnihandles::resolve (obj);   jint* addr = (Jint *) Index_oop_from_field_offset_long (P, offset); Return (Jint) (Atomic::cmpxchg (x, addr, e)) = = e; } unsafe_end

Eventually we finally saw the core code ATOMIC::CMPXCHG.

Continue to the bottom of the search, in the file java/jdk9u/hotspot/src/os_cpu/linux_x86/vm/atomic_linux_x86.hpp have such code:

inline jint     atomic::cmpxchg     (jint      exchange_value, volatile jint*     dest, jint      compare_value, cmpxchg_memory_order order)  {   INT MP  = OS::IS_MP ();   __asm__ volatile  (LOCK_IF_MP (% 4)   "cmpxchgl %1, ( %3) "                      :  "=a"   (exchange_value)                       :  "R"   (Exchange_value) ,  "A"   (compare_value),  "R"   (dest),  "R"   (MP)                       :  cc ", " Memory ");    return exchange_value; } 

We know by filename that, for different operating systems, JVMs should have different implementations for ATOMIC::CMPXCHG. Since our service is basically using 64-bit Linux, we will look at the implementation of Linux_x86.

Let's keep looking at the code:

__asm__ means this is a piece of inline assembly code. That is, use assembler code in C language.

The volatile here is a bit like JAVA, but not for memory visibility, but to tell the compiler that the code that accesses the variable is no longer optimized.

The meaning of Lock_if_mp (% 4) is simpler, if the operating system is multi-threaded, add a LOCK.

Cmpxchgl is the "comparison and exchange" of the assembly edition. But we know to compare and exchange, there are three steps, not atoms. So a LOCK is added to the multi-core case, and the CPU hardware guarantees his atomicity.

Let's see how LOCK is implemented. We went to Intel's official web site to see that lock in the early implementation of the Cup is directly blocking the bus, so that the realization of the visibility is very low efficiency. Later optimized for X86 CPU has the ability to lock a specific memory address, when this particular memory address is locked, it can prevent other system bus to read or modify this memory address.

On the bottom exploration of CAS we're done here. Let's summarize how the CAS is implemented in JAVA:

The CAs used by the Java unsafe is the CAS operation provided by this class.

Unsafe CAs is dependent on the JVM's implementation of ATOMIC::CMPXCHG for different operating systems

The implementation of ATOMIC::CMPXCHG uses a compiled CAS operation and uses the lock signal provided by CPU hardware to guarantee its atomic CAS application

Understand the principles of CAs let's go on to see the application of CAs: Spin locks

public class Spinlock {private atomicreference<thread> sign =new atomicreference<> ();     public void Lock () {Thread current = Thread.CurrentThread (); while (!sign. Compareandset (null, current) {}} public void Unlock () {Thread current = Thread.CurrentThread ()     ;   Sign. Compareandset (current, null); } }

The so-called spin lock, I think that the name of a considerable image, in the lock (), always while () loop until the CAS operation is successful. Atomicinteger's Incrementandget ()

Public final int Getandaddint (Object var1, long var2, int var4) {int var5;         do {VAR5 = This.getintvolatile (var1, var2);         while (!this.compareandswapint (var1, Var2, VAR5, VAR5 + VAR4));     return VAR5; }

This is the same thing as a spin lock, which is always while until the operation succeeds. token bucket Current limiter

The so-called token bucket limiter, is the system at a constant speed to increase the number of tokens in the bucket. Obtain a token from the token bucket before each request. Access is available only if a token is obtained. Refuse to provide service when there is no token in the token barrel. Let's look at how the Eureka Limiter uses CAS to maintain token and distribution in a multithreaded environment.

public class ratelimiter {     private final long  Ratetomsconversion;     private final atomicinteger consumedtokens  = new atomicinteger ();     private final atomiclong  Lastrefilltime = new atomiclong (0);      @Deprecated       public ratelimiter ()  {         this ( Timeunit.seconds);      }     public ratelimiter ( Timeunit averagerateunit)  {         switch  ( Averagerateunit)  {             case  SECONDS:                  ratetomsconversion = 1000;                 break;              case MINUTES:                  ratetomsconversion =  60 * 1000;                  break;             default:                  throw  new illegalargumentexception ("timeunit of "  + averageRateUnit + )  is not supported ");         }    &NBSP;&NBSP;}&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;//provides a way for the outside world to get  token       public  boolean acquirE (int burstsize, long averagerate)  {          Return acquire (Burstsize, averagerate, system.currenttimemillis ());      }     public boolean acquire (int burstsize, long  Averagerate, long currenttimemillis)  {         if   (burstsize <= 0 | |  averagerate <= 0)  { // instead of throwing exception, we  just let all the traffic go              return true;         }          //Add token          refilltoken (Burstsize, averagerate, currenttimemillis);          //consumption token         return  Consumetoken (burstsize);     }     private void  Refilltoken (Int burstsize, long averagerate, long currenttimemillis)  {          long refilltime = lastrefilltime.get ();          long timeDelta = currentTimeMillis -  refilltime;         //according to frequency calculation needs to increase how much  token          long newtokens = timedelta * averagerate /  rateToMsConversion;         if  (newtokens >  0)  {             long  newrefilltime = refilltime == 0                      ? currentTimeMillis                      : refillTime +  newtokens * ratetomsconversion / averagerate;              // CAS  guarantee that there is only one thread entering the fill               if  (Lastrefilltime.compareandset (refilltime, newrefilltime))  {                  while  (True)  {                      int currentlevel = consumedtokens.get ();                      int adjustedlevel =  math.min (currentlevel, burstsize); // in case burstsize decreased                       int newLevel =  (int)  math.max (0, adjustedlevel - newtokens);                       // while true  until the update is successful                       if  (Consumedtokens.compareandset ( Currentlevel, newlevel))  {                          return;                      }                  }              }         }      }     private boolean consumetoken (Int burstSize)  {         while  (True)  {              int currentlevel = consumedtokens.get ();              if  (currentlevel >=  burstsize)  {                  return false;              }             // while true  until no token  or   Get to so far              if  ( Consumedtokens.compareandset (currentlevel, currentlevel + 1))  {                  return true;              }          }     }     public void reset ()  {          consumedtokens.set (0);          lastrefilltime.set (0);      } }

So comb the role of CAS in token bucket limiters. is to ensure that in a multi-threaded situation, not blocking the thread's fill token and consumption token. Induction

Through the above three applications, we summarize the application scenarios of CAS:

The use of CAS can prevent thread blocking.

In most cases, we use a while true until we succeed. CAS Disadvantage

The problem with ABA is that a value changed from A to B and a, and the CAS operation did not reveal that the value had changed, and that the processing could be done using a version that carried a similar timestamp atomicstampedreference

Performance problems, most of the time we use the while true to modify the data until it succeeds. The advantage is that it is extremely fast, but when the number of threads keeps increasing, performance drops significantly, because each thread needs to execute, CPU time. Summary

CAS is one of the important ideas of the whole programming. There is a CAS figure in the implementation of the entire computer. The microscopic view of the compiled CAS is the cornerstone of the operating system-level atomic operation. From a programming language perspective, CAS is the cornerstone of multithreaded non-blocking operations. In the macroscopic view, in the distributed system, we can use the idea of CAS to utilize the external storage of similar redis, also can implement a distributed lock.

From a certain point of view, the architecture magnifies the micro implementation, or the underlying idea is to miniature the macro architecture. The mind of the computer is figured out, so understanding the underlying implementation can enhance the architecture capabilities, and the ability to enhance the architecture can also deepen the understanding of the underlying implementation. There is a myriad of computer knowledge, but limited routines. Grasp the foundation of several routines breakthrough, from the thinking and thinking of the angle of learning computer knowledge. Do not spend their energy on the continuous pursuit of new technology in the footsteps, follow the ' Start Guide line ' can only write a demo, the income is a demo just.

To stop and review the basics and classics may be a lot more technical.

I hope this article is helpful to everyone.

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.