面试官最爱问的问题集锦(三)

开课吧开课吧锤锤2021-03-10 11:56

    Java编程语言是一种简单、面向对象、分布式、解释型、健壮安全、与系统无关、可移植、高性能、多线程和动态的语言。如今Java已经广泛应用于各个领域的编程开发。

Java

    面试官:volatile关键字如何满足并发编程的三大特性的?

    那就要重提volatile变量规则:对一个volatile域的写,happens-before于后续对这个volatile域的读。这条再拎出来说,其实就是如果一个变量声明成是volatile的,那么当我读变量时,总是能读到它的最新值,这里最新值是指不管其它哪个线程对该变量做了写操作,都会立刻被更新到主存里,我也能从主存里读到这个刚写入的值。也就是说volatile关键字可以保证可见性以及有序性。

    继续拿上面的一段代码举例:

    inta=0;

    boolflag=false;

    publicvoidwrite(){

    a=2;//1

    flag=true;//2

    }

    publicvoidmultiply(){

    if(flag){//3

    intret=a*a;//4

    }

    }

    这段代码不仅仅受到重排序的困扰,即使1、2没有重排序。3也不会那么顺利的执行的。假设还是线程1先执行write操作,线程2再执行multiply操作,由于线程1是在工作内存里把flag赋值为1,不一定立刻写回主存,所以线程2执行时,multiply再从主存读flag值,仍然可能为false,那么括号里的语句将不会执行。

    如果改成下面这样:

    inta=0;

    volatileboolflag=false;

    publicvoidwrite(){

    a=2;//1

    flag=true;//2

    }

    publicvoidmultiply(){

    if(flag){//3

    intret=a*a;//4

    }

    }

    那么线程1先执行write,线程2再执行multiply。根据happens-before原则,这个过程会满足以下3类规则:

    程序顺序规则:1happens-before2;3happens-before4;(volatile限制了指令重排序,所以1在2之前执行)

    volatile规则:2happens-before3

    传递性规则:1happens-before4

    从内存语义上来看

    当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存

    当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效,线程接下来将从主内存中读取共享变量。

    以上内容由开课吧老师卡巴拉的树提供,更多Java教程尽在开课吧广场Java教程频道。

有用
分享