Java atomic class application scenarios such as: the use of AtomicInteger

 

There are some classes in Java that start with Atomic. We call this series of classes the atomic operation class. Atomic classes are built on CAS and volatile, CAS is a common implementation of non-blocking algorithms, which have better performance than synchronized, which is a blocking algorithm.

Take the simplest class, AtomicInteger, for example. It is equivalent to an int variable, and when we perform i++ of Int, it is not an atomic operation. The use of AtomicInteger's incrementAndGet guarantees atomic operations. The specific classes are as follows:

Without further ado, let's talk with examples.

Question: Now there are 2 threads, each of which increments the global integer variable i by 1. Each thread executes 5000 times. According to the traditional int usage, the code is as follows:

 

private static int m = 0;

public static void main(String[] args) throws InterruptedException {
    CountDownLatch cdl = new CountDownLatch(2);

    Thread t1 = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int j = 0; j < 5000; j++) {
                m++;
            }
            cdl.countDown();
        }
    });
    Thread t2 = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int j = 0; j < 5000; j++) {
                m++;
            }
            cdl.countDown();
        }
    });
    t1.start();
    t2.start();

    cdl.await();
    System.out.println("result=" + m);
}

 

Finally, when we execute the above code, the result may be 10000, but most of the time it is not 10000, but some random numbers. The problem here is m++. If we add the keyword synchronized to m++, the concurrency problem can also be solved. But synchronized is too heavy. So we can consider using the atomic operation class AtomicInteger to achieve. The specific implementation code is as follows:

 

public static void main(String[] args) throws InterruptedException {
    CountDownLatch cdl = new CountDownLatch(2);
    AtomicInteger i = new AtomicInteger(0);

    Thread t1 = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int j = 0; j < 5000; j++) {
                i.incrementAndGet();
            }
            cdl.countDown();
        }
    });
    Thread t2 = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int j = 0; j < 5000; j++) {
                i.incrementAndGet();
            }
            cdl.countDown();
        }
    });
    t1.start();
    t2.start();

    cdl.await();
    System.out.println("result=" + i.get());
}

Now no matter how many times we execute it, the result is always 10000.

illustrate:

  1. m++ is not an atomic operation, but incrementAndGet is an atomic operation method

Guess you like

Origin blog.csdn.net/qq_35222843/article/details/114314657