java的内存模型只保证了基本变量的读取操作和写入操作都必须是原子操作的,但是对于64位存储的long和double类型来说,JVM读操作和写操作是分开的,分解为2个32位的操作,

这样当多个线程读取一个非volatile得long变量时,可能出现读取这个变量一个值的高32位和另一个值的低32位,从而导致数据的错乱。要在线程间共享long与double字段必须在synchronized中操作或是声明为volatile。

这里使用volatile,保证了long,double的可见性,那么原子性呢?

<mark>其实volatile也保证变量的读取和写入操作都是原子操作,注意这里提到的原子性只是针对变量的读取和写入,并不包括对变量的复杂操作,比如i++就无法使用volatile来确保这个操作是原子操作。</mark>

总结:
其实最迷惑的地方就是为什么不是原子性,现在理解可见性,即,线程自己的工作内存,读取的是主内存的副本,因为加了volatile,所以在这个副本变量发生变化的时候必须立刻写入到主内存,后续线程读取主内存变量,就是最新的,这就是可见性,但是,在一些其他已经加载该变量副本的线程中,这个变量副本不会发生变化,并没有改变,所以volatilve并不是原子性的。