构建后可见的Java非final int

ric*_*chs 5 java concurrency

我有一个带有非final int变量的java类,我在构造函数中将其显式初始化为0.所有对变量的其他访问都由ReentrantLock管理.我是否必须担心线程不会看到0的初始值,因为我没有在构造函数中使用锁?

axt*_*avt 9

是的,你必须担心.为避免在这种情况下出现问题,您需要安全发布对象引用.

来自Java Concurrency in Practice:

要安全地发布对象,必须同时使对象的引用和对象的状态对其他线程可见.正确构造的对象可以通过以下方式安全发布:

  • 从静态初始化程序初始化对象引用;
  • 将对它的引用存储到volatile字段或AtomicReference中;
  • 将对它的引用存储到正确构造的对象的最终字段中; 要么
  • 将对它的引用存储到由锁正确保护的字段中.

在其他情况下,您可以(理论上)面对在new构造函数调用完成之前可用于其他线程的结果(由于可能的操作重新排序).

但请注意,如果0是默认值而不是构造函数中写入的值,则保证它是可见的(JLS§17.4.4):

  • 向每个变量写入默认值(零,false或null)与每个线程中的第一个操作同步.虽然在分配包含变量的对象之前将默认值写入变量似乎有点奇怪,但概念上每个对象都是在程序开始时使用其默认初始值创建的