面试-JMM的内存可见性

1.JAVA内存模型
在这里插入图片描述
分析:
由于JVM运行程序的实体是线程,而每个线程创建时,JVM都会 为其创建一个工作内存(栈空间),用于存储线程私有的数据。而java内存模型中规定所有变量都存储在主内存中。主内存是共享内存区域,所有线程都可以访问。但线程对变量的操作即读取,赋值等必须在工作内存中进行。首先将变量从主内存拷贝到自己的工作内存当中,然后对变量进行操作。操作完成后再将变量写回主内存。不能直接操作主内存中的变量,工作内存中存储着主内存中的变量的副本拷贝。工作内存是每个线程的私有区域,因此不同的线程间无法访问对方的工作内存。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
分析:
主内存属于共享数据区域,从某个角度讲包括了堆和方法区。而工作内存线程私有数据区域,从某个程度上将应该包括程序计数器,虚拟机栈,本地方法栈。
在这里插入图片描述
2.JMM如何解决可见性问题
把数据从内存加载到缓存,寄存器,
然后运算结束,写回主内存。
在这里插入图片描述
为了提高性能,处理器和编译器常常会对指令进行重排序。
在这里插入图片描述
3.happens-before原则
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
4.volatile机制
在这里插入图片描述
但是对于volatile变量运算操作,在多线程环境中,并不保证安全性。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
分析:
通过引入synchronized代码块,试图解决多线程请求单例时带来的重复创建单例的隐患。
原因在于某一个线程执行到第一次检测的时候,读到的instance不为空时,instance的引用对象可能还没完全初始化。因为instance = new Singleton()。可能分为一下三部完成。首先,分配对象内存空间,初始化对象,设置instance指向刚分配的内存地址。此时instance !=null.此时,可能会发生重排序。将第三部提前了。结果如上图右。先设置instance的内存地址,然后在初始化对象。这种情况单线程没有问题,但是多线程会发生问题。
所以,解决方式是使用volatile。

在这里插入图片描述
5.synchronized与volatile的区别
在这里插入图片描述

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值