一男子给对象转账5000元,居然又退还了!我就站在你面前,你却视而不见!文中,我们学习了线程安全的原子性和可见性,这篇文章就来说说有序性。

有序性

首先还是来看下概念,有序性就是指代码按照编写顺序执行

大家可能会有疑问,难道还会出现乱序执行吗?

因为编译器为了程序性能,可能会改变代码中语句的先后顺序,也就是指令重排序。比如:

String name = "wupx";
Integer age = 18;

编译器优化后可能变成:

Integer age = 18;
String name = "wupx";

在上述的情况中,指令重排序对运行结果没有什么影响,但是指令重排序的优化只能保证单线程程序中是线程安全的

如果在并发环境下,是不能保证有序性的,这就引出了有序性问题:

有序性问题

下面通过一个双重校验获取单例对象的例子,让大家了解下:

public class Singleton {
    private static Singleton instance; 

    public static Singleton getSingleton() {
        if (instance == null) {                         
            synchronized (Singleton.class) {
                if (instance == null) {       
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

这段代码的意思大致就是:首先判断 instance 是不是为空,如果为空,则进入同步代码块并进行再次判空操作,不然直接返回 instance。在同步代码块中再次判断 instance 是否为空,若仍然为空,则创建 Singleton 的实例 instance,其中第二次判空是为了避免了在进入同步代码块时间段内有线程已经创建了 Singleton 的实例。

哇,一个完美的单例模式的实现就完成了,其实并不是,因为代码中的 instance = new Singleton(); 这一行代码对应的 CPU 指令是三个:

  1. instance 分配一块内存 M
  2. 在内存 M 上初始化 Si