Deep parsing of Java Atomicinteger Atomic types

Source: Internet
Author: User
Tags cas volatile

Deep parsing of Java Atomicinteger Atomic types

In concurrent programming we need to ensure that the program can get the correct results when it is accessed concurrently by multiple threads, that is, thread safety. Thread safety is defined as follows:

This class is thread-safe when multiple threads access a class, regardless of how the runtime environment is scheduled or how those threads will be executed alternately, and if no additional synchronization or collaboration is required in the keynote code, and the class behaves correctly.

Example of a thread that is unsafe. If we want to implement a function to count Web page accesses, you might want count++ to use it to count traffic, but this self-increment operation is not thread-safe. count++can be divided into three operations:

    1. Gets the current value of the variable
    2. Gets the current variable value +1
    3. Write back the new value to the variable

Assuming that the initial value of Count is 10, when concurrent operations occur, both thread A and thread B may have performed 1 operations, followed by a 2 operation. A first to 3 operation +1, now the value is 11; Note that the current value that AB obtains is 10, so B performs a 3 operation, and the value of Count is still 11. The result is clearly not in line with our request.

So we need to use the protagonist--atomicinteger in this article to ensure thread safety.

The source code of Atomicinteger is as follows:

Package java.util.concurrent.atomic;import Sun.misc.Unsafe; Public classAtomicintegerextendsNumberImplementsJava.io.Serializable{Private Static Final LongSerialversionuid = 6214790243416807050L;//Setup to use Unsafe.compareandswapint for updates    Private Static Finalunsafe unsafe = unsafe.Getunsafe();Private Static Final LongValueoffset;Static{Try{Valueoffset = unsafe.Objectfieldoffset(Atomicinteger.class.Getdeclaredfield("Value")); }Catch(Exception ex) {Throw NewError (ex); }    }Private volatile intValue PublicAtomicinteger (intInitialValue) {value = InitialValue; } PublicAtomicinteger () {} Public Final int Get() {returnValue } Public Final void Set(intNewValue) {value = newvalue; } Public Final void Lazyset(intNewValue) {unsafe.Putorderedint( This, Valueoffset, NewValue); } Public Final int Getandset(intNewValue) { for(;;) {intCurrent =Get();if(Compareandset(current, NewValue))returnCurrent }    } Public Final Boolean Compareandset(intExpectintUpdate) {returnUnsafe.Compareandswapint( This, Valueoffset, expect, update); } Public Final Boolean Weakcompareandset(intExpectintUpdate) {returnUnsafe.Compareandswapint( This, Valueoffset, expect, update); } Public Final int getandincrement() { for(;;) {intCurrent =Get();intNext = current +1;if(Compareandset(current, next))returnCurrent }    } Public Final int getanddecrement() { for(;;) {intCurrent =Get();intNext = current-1;if(Compareandset(current, next))returnCurrent }    } Public Final int Getandadd(intDelta) { for(;;) {intCurrent =Get();intNext = current + Delta;if(Compareandset(current, next))returnCurrent }    } Public Final int Incrementandget() { for(;;) {intCurrent =Get();intNext = current +1;if(Compareandset(current, next))returnNext }    } Public Final int Decrementandget() { for(;;) {intCurrent =Get();intNext = current-1;if(Compareandset(current, next))returnNext }    } Public Final int Addandget(intDelta) { for(;;) {intCurrent =Get();intNext = current + Delta;if(Compareandset(current, next))returnNext }    } PublicStringtoString() {returnInteger.toString(Get()); } Public int Intvalue() {return Get(); } Public Long Longvalue() {return(Long)Get(); } Public float Floatvalue() {return(float)Get(); } Public Double Doublevalue() {return(Double)Get(); }}

Let's look at the properties defined in the Atomic integer class

   // setup to use Unsafe.compareAndSwapInt for updates    privatestaticfinal Unsafe unsafe = Unsafe.getUnsafe();    privatestaticfinallong valueOffset;    static {      try {        valueOffset = unsafe.objectFieldOffset            (AtomicInteger.class.getDeclaredField("value"));      catchthrownew Error(ex); }    }

Unsafe is a tool class inside the JDK, which mainly implements platform-related operations. The following quote

Sun.misc.Unsafe is a tool class used internally by the JDK. It exposes Java-layer code by exposing some of the "unsafe" features in Java, allowing the JDK to use Java code more to implement features that are otherwise platform-related and that require the use of native languages such as C or C + +. This class should not be used outside the JDK core class library.

The specific implementation of unsafe is not related to the goal of this article, you just need to know that this code is to get the value in the heap memory offset is enough. Offsets are important in Atomicinteger, and atomic operations are achieved by it.

Definition and volatile of value

The Atomicinteger itself is an integral type, so the most important attribute is value, and let's see how it declares value.

privatevolatileint value;

We see that value uses a volatile modifier, so what is it volatile ?

Volatile is equivalent to synchronized a weak implementation, that is volatile , the implementation of similar synchronized semantics, but there is no lock mechanism. It ensures that volatile updates to fields are communicated to other threads in a predictable manner.

volatileContains the following semantics:

  1. The Java storage model does not reorder the operations of the valatile instruction: This ensures that the operation of the volatile variable is performed in the order in which the instructions appear.
  2. Volatile variables are not cached in the register (only the owning thread is visible) or other places where the CPU is not visible, and the result of the volatile variable is always read from main memory each time. In other words, for changes to volatile variables, other threads are always visible and are not using variables inside their own thread stacks. That is, in the Happens-before rule, after a write operation to a valatile variable, any subsequent read operation understands the result of this write operation.

In short, the effect of volatile is that when a thread modifies a shared variable, another thread can read the modified value. In the analysis of Atomicinteger source code, we understand that this is enough.

Secure self-amplification with CAS operations

There are many methods in Atomicinteger, such as incrementAndGet() equivalent i++ and getAndAdd() equivalent i+=n . From the source code we can see that the implementation of these methods is very similar, so we mainly analyze incrementAndGet() the source code of the method.

The source code is as follows:

 public   Final  int  incrementandget  () {for  (; ;)            {int  current = get  ();            int  next = current + 1 ; if                 (compareandset  (current, next))        return  next; }} public  final  boolean   (int  expect, int  update) { unsafe. compareandswapint     (this , Valueoffset, expect, update); }

incrementAndGet()The method implements the self-increment operation. The core implementation is to get the current value and the target value (that is, value+1), and if compareAndSet(current, next) the return succeeds, the method returns the target value. So what is compareandset to do? To understand this approach we need to introduce CAS operations.

In the university operating system course we learned the concept of exclusive and optimistic locking. An exclusive lock is when a thread acquires a lock and all other threads need to be suspended until the thread that holds the exclusive lock releases the lock, and the optimistic lock assumes that there is no conflict to proceed directly, and if it fails because of a conflict, retry until the operation succeeds. The mechanism in which optimistic locking is used is cas,compare and Swap.

The CAS operation in Atomicinteger is the compareAndSet() function of extracting data from memory at each memory offset ( valueOffset ) , comparing the value taken with expect, and changing the value in memory to update if the data is consistent.

The use of CAs guarantees atomic manipulation. The principle of the remaining several methods is the same as this, which is no longer too much to explain.

Before looking at the Atomicinteger source code, I think its internal is used synchronized to implement atomic operations. Data is found to synchronized affect performance because locks in Java synchronized are exclusive locks, although atomic operations can be implemented, but the concurrency of this implementation is poor.

Summarize

Summing up, the main implementation of Atomicinteger in the atomic operation of the integer, to prevent the occurrence of abnormal results in concurrency, its internal mainly relies on the unsafe class in the JDK operating memory data to achieve. The volatile modifier guarantees that value can be seen in memory by other threads that it is worth changing. CAS operations ensure that Atomicinteger can safely modify value values.

Deep parsing of Java Atomicinteger Atomic types

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.