万字详解JVM,让你一文吃透( 九 )

  • 禁止指令重排序优化 。普通变量仅仅能保证在该方法执行过程中,得到正确结果,但是不保证程序代码的执行顺序 。
  • 为什么基于volatile变量的运算在并发下不一定是安全的?volatile变量在各个线程的工作内存,不存在一致性问题(各个线程的工作内存中volatile变量,每次使用前都要刷新到主内存) 。但是Java里面的运算并非原子操作,导致volatile变量的运算在并发下一样是不安全的 。
    为什么使用volatile?在某些情况下,volatile同步机制的性能要优于锁(synchronized关键字),但是由于虚拟机对锁实行的许多消除和优化,所以并不是很快 。
    volatile变量读操作的性能消耗与普通变量几乎没有差别,但是写操作则可能慢一些,因为它需要在本地代码中插入许多内存屏障指令来保证处理器不发生乱序执行 。
    并发与线程并发与线程的关系?并发不一定要依赖多线程,PHP中有多进程并发 。但是Java里面的并发是多线程的 。
    什么是线程?线程是比进程更轻量级的调度执行单位 。线程可以把一个进程的资源分配和执行调度分开,各个线程既可以共享进程资源(内存地址、文件I/O),又可以独立调度(线程是CPU调度的最基本单位) 。
    实现线程有哪些方式?
    • 使用内核线程实现
    • 使用用户线程实现
    • 使用用户线程+轻量级进程混合实现
    Java线程的实现操作系统支持怎样的线程模型,在很大程度上就决定了Java虚拟机的线程是怎样映射的 。
    Java线程调度什么是线程调度?线程调度是系统为线程分配处理器使用权的过程 。
    线程调度有哪些方法?
    • 协同式线程调度:实现简单,没有线程同步的问题 。但是线程执行时间不可控,容易系统崩溃 。
    • 抢占式线程调度:每个线程由系统来分配执行时间,不会有线程导致整个进程阻塞的问题 。
    虽然Java线程调度是系统自动完成的,但是我们可以建议系统给某些线程多分配点时间——设置线程优先级 。Java语言有10个级别的线程优先级,优先级越高的线程,越容易被系统选择执行 。
    但是并不能完全依靠线程优先级 。因为Java的线程是被映射到系统的原生线程上,所以线程调度最终还是由操作系统说了算 。如Windows中只有7种优先级,所以Java不得不出现几个优先级相同的情况 。同时优先级可能会被系统自行改变 。Windows系统中存在一个“优先级推进器”,当系统发现一个线程执行特别勤奋,可能会越过线程优先级为它分配执行时间 。
    线程安全的定义?当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方法进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象就是线程安全的 。
    Java语言操作的共享数据,包括哪些?
    • 不可变
    • 绝对线程安全
    • 相对线程安全
    • 线程兼容
    • 线程对立
    不可变在Java语言里,不可变的对象一定是线程安全的,只要一个不可变的对象被正确构建出来,那其外部的可见状态永远也不会改变,永远也不会在多个线程中处于不一致的状态 。
    如何实现线程安全?虚拟机提供了同步和锁机制 。
    • 阻塞同步(互斥同步)
    • 非阻塞同步
    阻塞同步(互斥同步)互斥是实现同步的一种手段,临界区、互斥量和信号量都是主要的互斥实现方式 。Java中最基本的同步手段就是synchronized关键字,其编译后会在同步块的前后分别形成monitorenter和monitorexit两个字节码指令 。这两个字节码都需要一个Reference类型的参数指明要锁定和解锁的对象 。如果Java程序中的synchronized明确指定了对象参数,那么这个对象就是Reference;如果没有明确指定,那就根据synchronized修饰的是实例方法还是类方法,去获取对应的对象实例或Class对象作为锁对象 。

    经验总结扩展阅读