根据<<深入理解Java虚拟机>>第12章的12.3.3节结尾部分的描述
假定T表示一个线程,V和W分别表示两个volatile型变量,那么在进行read、load、useassign、store和write操作时需要满足如下规则:
只有当线程T对变量V执行的前一个动作是load的时候,线程T才能对变量V执行use动作;
并且,只有当线程T对变量V执行的后一个动作是use的时候,线程T才能对变量V执行load动作。线程T对变量V的use动作可以认为是和线程T对变量V的load、read动作相关联的,必须连续且一起出现。
- 这条规则要求在工作内存中,每次使用V前都必须先从主内存刷新最新的值,用于保证能看见其他线程对变量V所做的修改。
又看到许多文章中说, Java内存模型实际上基于MESI协议
那么volatile型变量是每次都从主内存中重新获取变量, 还是基于MESI 协议, 只有当前处理器嗅探到了缓存中存储的值已经被修改而无效, 才从主内存中获取呢
在Java的内存模型中有工作内存的概念。Java内存模型规定所有的变量都是存在主存当中(类似于物理内存),每个线程都有自己的工作内存(类似于CPU高速缓存)。线程对变量的所有操作都必须在工作内存中进行,而不能直接对主存进行操作。并且每个线程不能访问其他线程的工作内存。
使用
volatile
关键字会强制将修改的值立即写入主存。因此假设有两个线程同时修改共享变量A,线程1修改会导致线程2中的工作内存缓存失效,所以线程2再次读取变量时会到主存中获取。volatile
关键字就是通过这种机制来保证可见性的。