The long and double assignments in Java are not atomic operations, since 32 bits are written, and then 32 bits are written, in two steps, so the thread is unsafe. If you change to the following, it's thread safe.
Private volatile long number = 8;
So, why is that so? Can the volatile keyword guarantee atomicity?
Java programmers are familiar with the phrase: volatile is only used to ensure that the variable for all threads of visibility, but not guaranteed atomicity. But in our case, volatile seems to be sometimes a substitute for a simple lock, and it seems that adding the volatile keyword saves the lock. Is it not contradictory to each other?
In fact, if a variable adds the volatile keyword, it tells the compiler and the JVM's memory model that the variable is shared across all threads, and each time the JVM reads the most recently written value and makes its newest value visible to all CPUs. So it's thread visibility that doesn't mention atomicity.
Below we use an example to show that volatile is not atomic, do not use volatile in getandoperate occasions (such occasions do not atoms, need to be locked, such as i++), only set or get the scene is suitable for volatile.
For example, you let a volatile integer increment (i++), in fact, to be divided into 3 steps: 1) Read the value of the volatile variable to local; 2) increase the value of the variable, 3) write the value of the local back, so that the other threads are visible. These 3-step JVM directives are:
mov 0xc (%r10),%r8d; Loadinc %r8d ; Incrementmov %r8d,0xc (%R10); Storelock Addl $0x0, (%RSP); Storeload Barrier
Note the last step is a memory barrier.
What is a memory barrier (Barrier)?
Memory barrier is a CPU instruction. Basically, it's such an instruction: a) to ensure the order in which certain operations are performed, and b) to affect the visibility of some data (which may be the result of some instruction execution). The compiler and CPU can reorder the instructions in the same way that the output is guaranteed, allowing performance to be optimized. Inserting a memory barrier is equivalent to telling the CPU and the compiler to execute before the command must be executed before the command must be executed. Memory barrier Another effect is to force updates to a different CPU cache at a time. For example, a write barrier flushes the data written before the barrier to the cache so that any thread that attempts to read the data will get the latest value, regardless of which CPU core or CPU is executing it.
What is the relationship between memory barrier (barrier) and volatile? As mentioned in the above virtual machine directive, if your field is Volatile,java the memory model will insert a write barrier directive after the write operation, inserting a read barrier command before the read operation. This means that if you write to a volatile field, you must know: 1. Once you have finished writing, any thread that accesses this field will get the most recent value. 2, before you write, will ensure that all previous events have occurred, and any updated data values are also visible, because the memory barrier will be the previous write values are flushed to the cache.
The following test code can actually test the self-increment of the voaltile without atomicity:
/*** Created by LHW on 16-7-29.*/ Public classDemo {Private Static volatile Long_longval = 0; Public Static voidMain (string[] args) {Thread T1=NewThread (Newloopvolatile ()); T1.start (); Thread T2=NewThread (NewLoopVolatile2 ()); T2.start (); while(T1.isalive () | |t2.isalive ()) {} System.out.println ("Final Val is:" +_longval); } Private Static classLoopvolatileImplementsRunnable { Public voidrun () {Longval = 0; while(Val < 10000000L) {_longval++; Val++; } } } Private Static classLoopVolatile2ImplementsRunnable { Public voidrun () {Longval = 0; while(Val < 10000000L) {_longval++; Val++; }}}} First result:FinalVal is:18683425Second Result:FinalVal is:15542661Third Result:FinalVal is:18549393
Obviously, the output is inconsistent, indicating that volatile does not guarantee the original sub-sex.
Java volatile does not guarantee atomicity