对于final域,编译器和处理器要遵守两个重排序规则。

  1. 在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序。
  2. 初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序。

以上规则保证只要对象是正确构造的,那么不需要使用同步(指lock和volatile的使用)就可以保证任意线程都能看到这个final域在构造函数中被初始化之后的值。要实现这个效果,还需要保证在构造函数内部,不能让这个被构造对象的引用为其它线程所见,也就是对象引用不能在构造函数中“逸出”,因为此时的final域由于重排序等原因可能还没被初始化。