谈谈对Volatile的了解
- volatile是JVM提供的轻量级的同步机制
volatile有三大个性
- 保障可见性
- 不保障原子性
- 禁止指令重排
JMM是什么
- JMM(Java内存模型,简称JMM)自身是一种形象的概念并不实在存在
- 因为JVM运行程序的实体是线程,而每个线程创立时JVM都会为其创立一个工作内存,工作内存是每个线程的公有数据区域,而Java内存模型中规定所有变量都存储到主内存,主内存是共享内存区域,所有线程都能够拜访,但线程对变量的操作必须在工作内存中进行。
- 首先要将变量从主内存拷贝到本人的工作内存空间,而后对变量进行操作,操作实现后再将变量写回主内存,不能间接操作主内存中的变量,因而不同的线程间无法访问对方的工作内存,线程间的通信(传值)必须通过主内存来实现。
数据传输速率:硬盘 < 内存 < < cache < CPU
下面提到的概念 主内存 和 工作内存:
- 主内存:次要包含本地办法区和堆
- 工作内存:属于该线程公有的栈和对主存局部变量拷贝的寄存器(包含程序计数器PC和cup工作的高速缓存区)
JMM的个性
JMM的三大个性:可见性,原子性,有序性
volatile只保障了两个,即可见性和有序性,不满足原子性
可见性(及时告诉)
- 指的是当主内存区域中的值被某个线程写入更改后,其它线程会马上通晓更改后的值,并重新得到更改后的值。
- 例如:有三个线程往主线程批改变量age=20,三个线程各自变量拷贝一份,其中一个线程在本人的工作空间将20改成了25,而后将工作内存中的值,写入主内存,主内存中的值被批改后,其余工作内存中的值会马上取得告诉。
用volatile验证可见性
咱们对于成员变量没有增加任何润饰时,是无奈感知其它线程批改后的值
class MyData { // 定义int变量 int number = 0; // 增加办法把变量 批改为 60 public void addTo60() { this.number = 60; }}
public class Test { public static void main(String[] args) { // 资源类 MyData myData = new MyData(); // 用lambda表达式创立线程 new Thread(() -> { System.out.println("线程进来了"); // 线程睡眠三秒,假如在进行运算 try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } // 批改number的值 myData.addTo60(); // 输入批改后的值 System.out.println("线程更新了number的值为" + myData.number); }).start(); // main线程就始终在这里期待循环,直到number的值不等于零 while (myData.number == 0) { } System.out.println("main办法完结了"); }}
最初线程没有进行,没有输入 main办法完结了 这句话,阐明没有用volatile润饰的变量,是没有可见性的。
当咱们给变量增加volatile关键字润饰:volatile int number = 0
,发现能够胜利输入完结语句。
⭐volatile 润饰的关键字,是为了减少主线程和线程之间的可见性,只有有一个线程批改了内存中的值,其它线程也能马上感知,是具备JVM轻量级同步机制的。