Home>Article>Java> Introduction to the role of the AtomicInteger atomic class (code example)

Introduction to the role of the AtomicInteger atomic class (code example)

不言
不言 forward
2019-03-02 14:49:00 2834browse

This article brings you an introduction to the role of the AtomicInteger atomic class (code examples). It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you. help.

The role of AtomicInteger atomic class

Multi-threaded operation, Synchronized has too much performance overhead and count is not an atomic operation. Because count needs to go through three steps of read-modify-write.

count is not an atomic operation. Because count needs to go through three steps of read-modify-write.

You can do this:

public synchronized void increase() { count++; }

Synchronized lock is exclusive, which means that if other threads are executing, the current thread can only wait!

Operation with CAS

CAS has 3 operands:

Memory value V old expected value A new value to be modified B when multiple threads try When CAS is used to update the same variable at the same time, only one of the threads can update the value of the variable (when A and the memory value V are the same, modify the memory value V to B), while other threads fail, and the failed thread will not be hung. Instead, you are told that you failed the competition and can try again (or do nothing).

We can find that there are two situations in CAS:

If the memory value V is equal to our expected value A, then the memory value is modified to B, and the operation is successful!

If the memory value V is not equal to our expected value A, there are generally two situations:

Retry (spin) and do nothing

Understand CAS The core is:

CAS is atomic. Although you may think there are two operations when you see compare and swap, it is atomic after all!

The atomic variable class is under the java.util.concurrent.atomic package. Overall, there are so many

Basic types:

AtomicBoolean: Boolean AtomicInteger: Integer AtomicLong: Long integer type

Array:

AtomicIntegerArray: Integer type in the array AtomicLongArray: Long integer type in the array AtomicReferenceArray: Reference type in the array

Reference type:

AtomicReference: Reference type AtomicStampedReference: Reference type with version number AtomicMarkableReference: Reference type with mark bit

Object’s properties

AtomicIntegerFieldUpdater: Object’s properties are integer Type AtomicLongFieldUpdater: The object's attribute is a long integer AtomicReferenceFieldUpdater: The object's attribute is a reference type

JDK8 new DoubleAccumulator, LongAccumulator, DoubleAdder, LongAdder

is an improvement on AtomicLong and other classes. For example, LongAccumulator and LongAdder are more efficient than AtomicLong in high concurrency environments. The classes in the Atomic package are basically wrapper classes implemented using Unsafe

There are several methods (CAS) we like in Unsafe:

// 第一和第二个参数代表对象的实例以及地址,第三个参数代表期望值,第四个参数代表更新值 public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5); public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5); public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

Using atomic variable classes

class Count{ // 共享变量(使用AtomicInteger来替代Synchronized锁) private AtomicInteger count = new AtomicInteger(0); public Integer getCount() { return count.get(); } public void increase() { count.incrementAndGet(); } }

ABA problem of atomic class

The following operations can be executed normally. What problems will occur if this happens? ? Thread C cannot know the count values modified by thread A and thread B, which is risky.

Now I have a variable count=10. Now there are three threads, namely A, B, C. Thread A and thread C read the count variable at the same time, so the memory value and expected value of thread A and thread C Both are 10. At this time, thread A uses CAS to modify the count value to 100. After modification, at this moment, thread B comes in and reads the value of count as 100 (the memory value and expected value are both 100), and changes the count value to 100. The value is changed to 10. Thread C gets the execution right and finds that the memory value is 10 and the expected value is also 10. Change the count value to 11

solve the ABA problem

To solve the ABA problem, we You can use the AtomicStampedReference and AtomicMarkableReference classes provided by the JDK.

Simply put, it provides a version for this object, and if this version is modified, it will be automatically updated.

The principle is probably: a Pair object is maintained, and the Pair object stores our object reference and a stamp value. Each time CAS compares two Pair objects

LongAdder has better performance than AtomicLong

When using AtomicLong, a large number of threads will compete to update the same atomic variable at the same time under high concurrency, but due to the simultaneous Only one thread's CAS will succeed, so other threads will continue to try to spin and try CAS operations, which will waste a lot of CPU resources.

LongAdder can be summarized as follows: the internal core data value is separated into an array (Cell). When each thread accesses it, it is mapped to one of the numbers for counting through hashing and other algorithms, and the final counting result is, It is the summation and accumulation of this array.

Simply put, one value is dispersed into multiple values, which can spread the pressure during concurrency and improve performance.


The above is the detailed content of Introduction to the role of the AtomicInteger atomic class (code example). For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:segmentfault.com. If there is any infringement, please contact admin@php.cn delete