两台电脑一台做服务器 网站,网站前端建设都需要什么问题,互联网 网站定制,下载手机app软件文章目录 内存模型内存可见性解决方案volatile 内存模型
什么是JAVA 内存模型#xff1f;
Java Memory Model (JAVA 内存模型#xff09;是描述线程之间如何通过内存(memory)来进行交互。 具体说来#xff0c; JVM中存在一个主存区#xff08;Main Memory或Java Heap Mem… 文章目录 内存模型内存可见性解决方案volatile 内存模型
什么是JAVA 内存模型
Java Memory Model (JAVA 内存模型是描述线程之间如何通过内存(memory)来进行交互。 具体说来 JVM中存在一个主存区Main Memory或Java Heap Memory对于所有线程进行共享而每个线程又有自己的工作内存Working Memory工作内存中保存的是主存中某些变量的拷贝线程对所有变量的操作并非发生在主存区而是发生在工作内存中而线程之间是不能直接相互访问变量在程序中的传递是依赖主存来完成的。
Java虚拟机规范中定义了Java内存模型. 目的是屏蔽掉各种硬件和操作系统的内存访问差异以实现让Java程序在各种平台下都能达到⼀致的 并发效果.
Java内存模型的抽象示意图如下
线程之间的共享变量存放在主内存中Main Memory每个线程都有自己的工作内存Working Memory当线程要读取一个共享变量时会先将变量拷贝到工作内存中再从工作内存中读取变量当线程要修改一个共享变量时也是先修改工作内存中的副本再同步到主内存中
此时引入了两个问题
为什么要引入这么多的内存为什么要麻烦的拷贝来拷贝去 为什么要引入这么多的内存 实际上并没有那么多的内存只是Java规范中的一个术语是属于抽象的叫法 所谓的主内存才是硬件角度真正的内存而工作内存则是指CPU的寄存器和缓存器 为什么要麻烦的拷贝来拷贝去 因为CPU访问寄存器的速度以及访问缓存器的速度远快于访问内存快了将近 3-4个数量级也就是几千倍上万倍 比如在代码中需要连续10次读取某个变量的值如果10次都从内存中读那么速度是很慢的。 但如果第一次从内存中读将结果缓存到寄存器中那么后面9次的访问就不必访问内存了效率就提高了 说明白了内存模型来说说什么是内存可见性
内存可见性
内存可见性Memory Visibility是指当某个线程正在使用对象状态而另一个线程在同时修改该状态需要确保当一个线程修改了对象状态后其他线程能够立即看到发生的状态变化。
由于线程之间的交互都发生在主内存中但对于变量的修改又发生在自己的工作内存中经常会造成读写共享变量的错误我们也叫可见性错误。
可见性错误是指当读操作与写操作在不同的线程中执行时我们无法确保执行读操作的线程能适时地看到其他线程写入的值有时甚至是根本不可能的事情。
解决方案
我们可以通过同步来保证对象被安全地发布。我们可以使用一种轻量级的volatile变量
volatile 代码在写入volatile修饰的变量时
改变工作内存中volatile变量副本的值将改变后的副本的值从工作内存中同步到主内存中
代码在读取volatile修饰的变量时 从主内存中读取最新的值到新的线程的工作内存中 从工作内存中读取volatile变量的副本 加上volatile虽然使速度变慢了但是数据变得更准确了。public class test{static class Counter {public int flag 0;}public static void main(String[] args) {Counter counter new Counter();Thread t1 new Thread(() - {while (counter.flag 0) {// do nothing}System.out.println(循环结束!);});Thread t2 new Thread(() - {Scanner scanner new Scanner(System.in);System.out.println(输⼊⼀个整数:);counter.flag scanner.nextInt();});t1.start();t2.start();}
}//执行代码后
//输入一个非零的值程序并没有结束 如上t1读的是自己的工作内存中的内容 当t2对flag变量进行修改时此时t1感知不到t2的变化 如果给flag加上volatile
static class Counter {public volatile int flag 0;
}
// 执⾏效果
// 当⽤⼾输⼊⾮0值时, t1 线程循环能够⽴即结束.以上就是本文所有内容如果对你有帮助的话点赞收藏支持一下吧