• [Java复习] 面试突击


    谈谈你对Java内存模型的理解?

    Java内存模型8个指令:lock、unlock、read、load、use、assign、store、write

    两个线程同时执行data++;操作时,Java内存工作流程:

    你知道Java内存模型中的原子性、可见性、有序性是什么?

    连环炮 :Java内存模型 -> 原子性、可见性、有序性 -> volatile -> happens-before -> 内存屏障

    原子性:线程1对i++时,线程2不能对i++同时进行。同时刻只有一个线程对一个值进行操作。

                     i++必须独立执行,但默认时线程不安全的。

    可见性:线程1操作i++后,强制线程2操作i时,必须从主内存中刷新更新后的i的值。

    有序性:对于代码,还有一个问题时指令重排序,编译器和指令器,有时候为了提高代码执行效率,会将指令重排序。

    具备有序性,不会发生指令重排导致代码异常;不具有有序性,会发生指令重排,导致代码可能会出现一些问题。

    能从Java底层角度聊聊volatile关键字的原理?

    volatile用来解决可见性和有序性,在有些罕见条件下,可以有限保证原则性,但主要不是保证原则性的。

    将volatile要从内存模型开始讲起,还有原子性,可见性,有序性。

    使其他工作线程内存中的值缓存失效,强制从主内存中读取新值,即可见性。

    在很多开源中间件系统源码里都有多线程并发,大量使用volatile关键字。

    指令重排以及happens-before原则是什么?

    volatile关键字和有序性的关系,volatile是如何保证有序性的,如何避免发生指令重排的?

    编译器、指令器可能对代码重排序,乱排,要遵守一定的规则,happens-before原则,只要符合happens-before的原则,那么就不能胡乱重排。

    程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作。

    锁定规则:一个unLock操作先行发生于后面对同一个锁的lock操作,比如说在代码里有先对一个lock.lock(),lock.unlock(),lock.lock()。

    volatile变量规则:对一个volatile变量的写操作先行发生于后面对这个volatile变量的读操作,volatile变量写,再是读,必须保证是先写,再读。

    传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C。

    线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作,thread.start(),thread.interrupt()。

    线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生。

    线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行。

    对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始。

          

    用volatile来修饰flag后,一定可以让prepare()指令在flag=true之前先执行,禁止指令重排。

    参考资料:

    互联网Java工程师面试突击(第三季)-- 中华石杉

  • 相关阅读:
    在Fedora 20下使用TexturePacker
    实战微信JS SDK开发:贺卡制作与播放(1)
    Fedora 20下安装Google PinYin输入法
    Netty5 时间服务器 有粘包问题
    Netty5入门学习笔记003-TCP粘包/拆包问题的解决之道(下)
    Netty5入门学习笔记002-TCP粘包/拆包问题的解决之道(上)
    11g Rac 添加日志组
    工作中的生长与完善——Leo鉴书86
    搜集直方图repeat和skewonly
    com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxError Exception
  • 原文地址:https://www.cnblogs.com/fyql/p/12132565.html
Copyright © 2020-2023  润新知