Some doubts about volatile and Atomic classes?

前端 未结 2 1140
野性不改
野性不改 2021-01-21 00:18

i am going thru Java threads book. I came across this statement

Statement 1:- \"volatile variables can be safely used only for single load or store oper

相关标签:
2条回答
  • 2021-01-21 01:06

    Statement 1:- "volatile variables can be safely used only for single load or store operation and can't be applied to long or double variales. These restrictions make the use of volatile variables uncommon"

    What?! I believe this is simply flat-out wrong. Maybe your book is out of date.

    Statement 2:- "A Volatile integer can not be used with the ++ operator because ++ operator contains multiple instructions.The AtomicInteger class has a method that allows the integer it holds to be incremented atomically."

    Exactly what it says. The ++ operator actually translates to machine code like this (in Java-like pseudocode):

    sync_CPU_caches();
    int processorRegister = variable;
    processorRegister = processorRegister + 1;
    variable = processorRegister;
    sync_CPU_caches();
    

    This is not thread-safe, because even though it has a memory barrier, and reads atomically, and writes atomically, it is not guaranteed that you won't get a thread switch in the middle, and processor registers are local to a CPU core (think of them as like "local variables" inside the CPU core). But an AtomicInteger is thread-safe - it probably is implemented using special machine code instructions such as compare-and-swap.

    0 讨论(0)
  • 2021-01-21 01:13

    The main purpose of volatile variables is not to cause immediate thread-safe access to that variable, but to ensure a so called happens-before safety.

    Theoretically a call to

    volatile int i = 0;
    

    and

    int i = 0;
    

    has no difference, as a 32-bit word is written atomically anyways (on 32 bit and higher machines to be correct). Since pointers are 32/64 bit ints as well internally, there is basically only one operation that volatile makes atomically, and that is if you use a 64 bit long in a 32 bit environment.

    The happens-before however is something that actually messes up the above example. To understand this you need to know that threads don't use the actual memory of the variable in question but might make copies of it to speed up execution and can re-order the statements for optimization. Now if you have something like:

    Thread A: value = 1; doIt = true;
    Thread B: if (doIt) { doDoIt(value); }
    

    It is possible that in Thread B doIt is true, but value is not yet 1, because the order of execution might have been changed by the JVM, or the new value has just not yet been broadcasted to the copy of Thread B's value.

    If doIt is declared volatile instead, then at the moment of accessing it, the JVM ensures that all code before that access has already been executed and broadcasted. So the above example is the actual reason to use volatile.

    0 讨论(0)
提交回复
热议问题