When I was doing code reading, I hit a class called ʻAtomicReference`, so I looked it up.
According to the Reference (https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicReference.html)
Atomicly updated object reference
That thing. I don't know if this is all, but when performing concurrent programming, keep the shared objects that you want to update. The syncronize
is expensive, and the violatile
keyword breaks when written at the same time.
volatile
Although derailed, the intent of the volatile
keyword is to ensure that the variable reference refers to the main memory, not the CPU cache. Variables without this keyword usually refer to the CPU cache. In a system with multiple CPUs, the same value may not always be referenced. Therefore, if you add the volatile
keyword, it will refer to the main memory even if the CPU running is different, so it is guaranteed to refer to the same one. Therefore, it is also called "guarantee of visibility". By the way, the meaning of volatile
is easy to change.
private volatile int counter = 0;
By the way, the description on this site was great to understand. It's a site called Java Concurrency
, so you can expect other articles.
AtomicReference
AtmoicReference, on the other hand, is a mechanism for referencing and updating 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
If you specify the type like this, you can keep the value or refer to it with the get ()
method. If nothing is passed 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 in two threads, it will be the value updated later. If that's okay, that's fine. So there are methods like getAndUpdate ()
. Pass in a lambda expression to update based on the current value. Some methods have the order of ʻupdate and
get` reversed.
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()
Some methods write only when the value is expected. The return value is boolean
, so you can tell if it was the expected value. This ensures that it has not been updated in any other 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 about it, the implementation is the same as compareAndSet
up to Java8, and from Java9 it seems to be deprecated, so forget about it.
Reference
Recommended Posts