你的Java并发程序Bug,100%是这几个原因造成的(2)
有序性:程序执行的顺序按照代码的先后顺序执行,比如下面这段代码
按照有序性的话就需要按照代码的顺序执行下来,但是执行结果不一定是按照这个顺序来的,因为 JVM 为了提高程序的运行效率,会对上面的代码按照 JVM 编译器认为较好的顺序执行,从而可能打乱代码的执行顺序,是它会保证程序最终执行结果和代码顺序执行的结果是一致的,这也就是我们所说的指令重排序 由于指令重排序造成程序出 Bug 的典型案例就是:未加 volatile 关键字的双重检测锁单例模式,如下代码:
双重检测锁方案看上去非常完美,但是在实际运行时却会出 Bug,会出现对象逸出的问题,可能会得到一个未构建完的 Singleton 对象, 这个就是在构建 Singleton 对象时指令重排序的问题。我们先来看看构建对象理想型的操作指令:
但是实际在 JVM 编译器上可能不是这样,可能会被优化成如下指令:
看上去一个小小的优化,也就是这么一个小小的优化就会使你的程序不安全,假设抢到锁的线程执行完指令2 之后,此时的 instance 已经不为空了,这时候来了线程C,线程C 看到的 instance 已经是不为空的了,就会直接返回 instance 对象,这时候的 instance 并未初始化成功,调用 instance 对象的方法或者成员变量时将有可能触发空指针异常。可能的执行流程图: 未加 volatile 关键字的双重检测锁单例模式 上面就是造成 Java 程序在多线程情况下出 Bug 的三种原因,关于这些问题 JDK 公司也给出了相应的解决办法,具体如下图所示,这些解决办法的更多细节,我们后面在细细道来。 并发解决机制
(编辑:ASP站长网) |