你要知道java内存模型中每个线程都有自己的工作内存,这个工作内存包括CPU寄存器、L1缓存。首先volatile关键字有两种作用,第一种是保证可见性、第二种是禁止指令重排序。我们先说第一种保证可见性:又分为volatile读和volatile写,在hotspotVM实现中,volatile读使用的是C语言中的volatile关键字(想深入了解的话可以去看hotspot源码中的byteInterpreter.cpp文件),c语言中的volatile关键字就是告诉编译器不要对该关键字修饰的变量进行优化(也就是不要缓存在寄存中,每次都从内存中取最新的值)。而volatile写:则是使用了lock指令:该指令是对缓存行加锁,从而同一时刻只有一个线程可以访问该变量,而且会立即将最新值刷入内存,从而保证了volatile变量写入内存这个行为的原子性和可见性。注意这里只是保证了写入内存这个过程的原子性。至于你说的MESI,这是intel cpu产品下的缓存一致性协议,它只针对缓存行,本质上是各个cpu核心通过总线进行交流,使其它核心的L1?L2缓存中的缓存行失效。假设这里有一个没有volatile修饰的变量a、有两个线程同时对该变量执行a++操作,这种情况就是你说的仅有mesi的情况:线程A的代码由CPU核心A执行,线程B的代码由CPU核心B执行,首先核心A先将变量a加载到L1缓存的缓存行中,此时该缓存行的状态为E,表示由A独占,然后A将混存行中a变量的值加载到寄存器中准备执行+1操作,这个时候核心A收到核心B的消息:请求将a的值共享给B核心,随后A核心通过总线将a共享给B核心,此时两个核心的缓存行状态都变为S,这个时候B核心要修改a变量的值,就发送失效消息给A核心,但是A核心已经将a的值加载到寄存器中了,失效与否都没有用了,因为mesi作用于缓存行,对于已经加载到寄存器中的值毫无卵用。所以AB两个核心的值相同,都执行a++操作,最后得到的值也相同。如果使用了volatile变量,还是可能存在这个问题,因为volatile只保证了写入内存过程的原子性,对于已经加载到寄存器中的值也无能为力。所以要保证整个a++行为的原子性才能保证线程安全问题!