CAS issue with AtomicInteger - Stack Overflow
我想大声告诉你
我想大声告诉你 2017-06-28 09:24:31
0
1
792
 public final int incrementAndGet() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return next;
        }
    }

This is an auto-increment operation, definition: CAS has 3 operands, memory value V, old expected value A, and new value to be modified B. If and only if the expected value A and the memory value V are the same, modify the memory value V to B, otherwise do nothing
Is the expected value next? The memory value is current?
If there is no competition from other threads when a thread is incremented, then the expected value should be 1 greater than the memory value. How come the expected value and the memory value are the same?

我想大声告诉你
我想大声告诉你

reply all(1)
刘奇

Laxative~
Maybe the author’s understanding of the question is a bit wrong

  1. current is the expected value, not the memory value

  2. next is the modified new value, not the expected value

The source code of the

methodcompareAndSet can be seen, and the comments inside are very clear

/**
     * Atomically sets the value to the given updated value
     * if the current value {@code ==} the expected value.
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful. False return indicates that
     * the actual value was not equal to the expected value.
     */
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

The operation of CAS is as mentioned by the questioner. It compares the expected value with the memory value. Only when they are equal, the new value will be written. Otherwise, it will keep retrying. This is an optimistic attitude, and the real memory value In fact, it is the attribute AtomicInteger.value (actually the most important thing is not this attribute, it is just a reference, the real boss will mention it later). Note that this value is modified by the keyword volatile

private volatile int value;

So this value is actually a shared variable, which represents the visibility of this variable, that is, the visibility between threads,

======================== I’m just talking too much about visibility, if you don’t like it you can just skip it =========== =====================

To put it simply, the Java memory model stipulates that variables are stored in main memory (similar to physical memory). Each thread has its own work cache. When operating on a variable, the value in the main memory is not directly modified, but It is executed in its own work cache, and finally synchronized to the main memory, and threads cannot access each other's work cache

The visibility mentioned here means that when a thread operates a variable modified with the keyword volatile, ​​when the variable is successfully modified and written to the main memory, the variables in the work cache of other threads will become invalid. So at this time, when other threads read the variable again, they will read it directly from the main memory instead of using the value in their own working cache

==========================================Finished====== =========================================

I just mentioned that the AtomicInteger.value attribute is just a reference to the data itself. When calling the compareAndSet method, you can notice the second parameter, valueOffset. In fact, this is the key... Really Boss, the real memory value, because it involves a word rarely heard in the Java language, pointer, this valueOffset is actually the offset within the object, this is the real memory value

(The reason why this method compareAndSet calls the method of Unsafe class, Unsafe actually encapsulates some pointer-like operations, pointers are not safe)

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template