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的区别