In this article, we take AtomicInteger as an example to explain how CAS (Compare And Swap) is used in AtomicInteger, And the Unsafe object that provides CAS.

Let’s start with an example. Suppose we now want to implement incrementing int values (single application range) in multi-threaded applications. What should we do?

The first thing you might think of is using the synchronized keyword, which looks like this:

private static volatile int value; public static void main(String[] args) { Runnable run = new Runnable() { @Override public void run() { for (int i = 0; i < 1000; i++) { increaseBySync(); }}}; Thread t1 = new Thread(run); Thread t2 = new Thread(run); t1.start(); t2.start(); while (Thread.activeCount() > 1) { Thread.yield(); } System.out.println(value); } private static synchronized int increaseBySync() { return value++; }Copy the code

The above example has two threads increment the value variable at the same time, which achieves thread-safe increment of int by adding a synchronized lock to the increaseBySync method.

Synchronized performance problems

When multiple threads access a syncronized method or block of code, there is a significant performance cost associated with switching between threads and the amount of time other threads wait (depending on the OS implementation, there is uncertainty). Since JDK5, we can use Java. Util. Concurrent. The atomic package provided by some of the tools, to achieve the above functions, AtomicInteger is one of the class, it USES the function of CPU level of CAS, using it we can write more efficient code.

private static AtomicInteger atomicInteger = new AtomicInteger(0); public static void main(String[] args) { Runnable run = new Runnable() { @Override public void run() { for (int i = 0; i < 1000; i++) { atomicInteger.incrementAndGet(); }}}; Thread t1 = new Thread(run); Thread t2 = new Thread(run); t1.start(); t2.start(); while (Thread.activeCount() > 1) { Thread.yield(); } System.out.println(atomicInteger.get()); }Copy the code

The above code can achieve the same effect of multi-threading, but more efficiently.

AtomicInteger source code analysis

Let’s take a look at how AtomicInteger is implemented internally.

private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;

static {
  try {
    valueOffset = unsafe.objectFieldOffset
    (AtomicInteger.class.getDeclaredField("value"));
  } catch (Exception ex) { throw new Error(ex); }
}

private volatile int value;
Copy the code

First, it has a volatile int variable value. Volatile is used to make updates to the value visible to each thread. See the link at the end of this article for an introduction to volatile.

The key here is objects of the Unsafe type. By its name the JDK developers want to tell us that it is not secure, but it provides some functionality that the JVM does not, such as CAS.

CAS

Here is a method in the AtomicInteger class that calls the CAS function through the Unsafe object. CAS is a feature provided by almost all cpus today, and it is atomic operation, with which many efficient functions can be achieved.

public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
Copy the code

Other atomic tool classes

Java. Util. Concurrent. Atomic package atomic below at the beginning of classes are implemented based on CAS, we are interested can look at the source code, if you understand what is said above, the other are very similar.

  • AtomicBoolean
  • AtomicIntegerArray
  • AtomicLong
  • AtomicReference
  • .

Other articles

The Java concurrency volatile keyword

Demo code location


SRC/main/Java/net/weichitech/juc/AtomicIntegerTest. Java, small western/Java programming – learning – Gitee.com