[Java] A private note about AtomicReference

2 minute read

When I was reading the code, I hit a class called AtomicReference, so I checked it.

What is # Atmoic Reference

According to reference

A reference to the atomically updated object

With that. I don’t know if this is the only thing, but when carrying out concurrent programming, keep the shared objects that you want to update. syncronize is expensive, and the violatile keyword breaks when written at the same time.

volatile

It is a digression, but the intention of the volatile keyword is to guarantee that the variable reference refers to the main memory, not the CPU cache. Variables without this keyword usually refer to the CPU cache. For systems with multiple CPUs, the same value may not always be referenced. Therefore, if you add the volatile keyword, the main memory is referenced even if the CPU that is executing is different, so it is guaranteed that the same thing is referenced. Therefore, it is also called “guarantee of visibility”. By the way, the meaning of volatile is a transitional meaning.

private volatile int counter = 0;

By the way, the explanation on this site was the best to understand. Since it is a site called Java Concurrency, you can expect other articles.

AtomicReference

On the other hand, AtmoicReference is a mechanism to refer and update from multiple threads without locking the lock with synchronized.

get()

AtomicReference<Integer> atomic = new AtomicReference<>();
System.out.println("atomic: "+ atomic.get());

atomic = new AtomicReference<>(10);
System.out.println("atomic: "+ atomic.get());

result

atomic: null
atomic: 10

By specifying the type like this, you can retain the value or refer to it by the get() method. If you pass nothing to the constructor, it will be initialized with null.

set()

A set of values.

atomic.set(100);
System.out.println("atomic: "+ atomic.get());

result

atomic: 100

getAndUpdate()

Normally, I don’t think you use set() that much. If it is updated by two threads, it will be the value updated later. If that’s OK, that’s fine. So there are methods like getAndUpdate(). Pass in a lambda expression and update based on the current value. Some methods have the reverse order of update and get.

UnaryOperator operator = (v) -> (Integer)v + 1;
System.out.println("atomic getAndUpdate: "+ atomic.getAndUpdate(operator));
System.out.println("atomic after getAndUpdate: "+ atomic.get());

System.out.println("atomic updateAndGet: "+ atomic.updateAndGet(operator));

result

atomic getAndUpdate: 20
atomic after getAndUpdate: 21
atomic updateAndGet: 22

compareAndSet()

There is also a method to write only when it is the expected value. The return value is boolean, so I know if it was what I expected. This ensures that it has not been updated by another thread.

            # At this point the value is 22
atomic.compareAndSet(23, 100);
System.out.println("compareAndSet maybe not updated: "+ atomic.get());

result

compareAndSet maybe not updated: 22

By the way, there was a method called weakCompareAndSet, and the result was the same, so why? If you think that, up to Java8, the implementation is the same as compareAndSet, and since Java9 seems to be deprecated, please forget it.

Reference

Tags:

Updated: