一、谈谈你对voliatle的理解
1.voliatle是Java虚拟机提供的轻量级的同步机制
- 保证可见性
- 不保证原子性
- 禁止指令重排
2.JMM你谈谈(线程安全性得到保证)
- 可见性
- 原子性
- VolatileDemo代码演示可见性+原子性代码
package com.interview; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; class MyData { volatile int number = 0; public void addTo60() { this.number = 60; } //注意 此时number不保证原子性 public void addPlusPlus(){ number++; } AtomicInteger atomicInteger=new AtomicInteger(); public void addMyAtomic(){ atomicInteger.getAndIncrement(); } } public class VoliatleDemo { /** * 1 验证volatile的可见性 * 1.1.假如int number=0;number变量之前根本没有添加volatile关键字修饰 没有可见性 * 1.2 添加了volatile可以解决可见性问题 * * 2 验证volatile不保证原子性 * 2.1 原子性指的是什么意思? * 不可分割 完整性 也即某个线程正在做某个具体业务时 中间不可以被加塞或者分割。 需要整体完整要么同时成功 要么同时失败。 * 2.2 是否可以保证原子性的案例 * * @param args */ public static void main(String[] args) { seyOkByVolatile(); MyData myData = new MyData();//资源类 for (int i = 1; i <20 ; i++) { new Thread(() -> { for (int j = 1; j <1000 ; j++) { myData.addPlusPlus(); myData.addMyAtomic(); } },String.valueOf(i)).start(); } //需要等待上面20个线程都全部计算完成后 再用mian线程取得最终的结果值看是多少? while(Thread.activeCount() >2 ){//说明线程还没有算完 Thread.yield();//礼让线程 } System.out.println(Thread.currentThread().getName()+"\t int type,finally number value:"+myData.number); System.out.println(Thread.currentThread().getName()+"\t AtomicInteger type,finally number value:"+myData.atomicInteger); } //volatile可以保证可见性。 及时通知其他线程 主物理内存的值已经修改 private static void seyOkByVolatile() { MyData myData = new MyData();//资源类 new Thread(() -> { System.out.println(Thread.currentThread().getName()+"\t come in"); //暂停一会线程 try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } myData.addTo60(); System.out.println(Thread.currentThread().getName()+"\t updated number value" + myData.number); },"AAA").start(); while (myData.number==0){ //mian线程就一直再这里等待循环直到number值不在等于零 } System.out.println(Thread.currentThread().getName()+"\t mission is over"); } }
- 有序性
加了volatile,禁止指令重排
指令重排案例
public class ReSortSeqDemo {
int a=0;
boolean flag=false;
public void method01(){
a=1;
flag=true;
}
//多线程环境中线程交替执行由于编译器优化重排的存在
//俩个线程中使用的变量能否保证一致性是无法确定的 结果无法预测
public void method02(){
if(flag){
a=a+5;
System.out.println("teValue"+a);
}
}
}
3.你在那些地方用过volatile?
- 单例模式 DCL代码
- 单例模式volatile分析
public class SingletonDemo {
private static volatile SingletonDemo instance=null;
private SingletonDemo(){
System.out.println(Thread.currentThread().getName()+"\t 我是构造方法SingletonDemo");
}
//DCL Double Check Lock 双端检索机制
public static SingletonDemo getInstance(){
if(instance == null){
synchronized (SingletonDemo.class){
if(instance==null){
instance=new SingletonDemo();
}
}
}
return instance;
}
public static void main(String[] args){
/* //单线程(main线程的操作动作)
System.out.println(SingletonDemo.getInstance()==SingletonDemo.getInstance());
System.out.println(SingletonDemo.getInstance()==SingletonDemo.getInstance());
System.out.println(SingletonDemo.getInstance()==SingletonDemo.getInstance());
*/
for (int i = 1; i <=10 ; i++) {
new Thread(() -> {
SingletonDemo.getInstance();
},String.valueOf(i)).start();
}
}
}