我有一个带有非final int变量的java类,我在构造函数中将其显式初始化为0.所有对变量的其他访问都由ReentrantLock管理.我是否必须担心线程不会看到0的初始值,因为我没有在构造函数中使用锁?
是的,你必须担心.为避免在这种情况下出现问题,您需要安全发布对象引用.
来自Java Concurrency in Practice:
要安全地发布对象,必须同时使对象的引用和对象的状态对其他线程可见.正确构造的对象可以通过以下方式安全发布:
- 从静态初始化程序初始化对象引用;
- 将对它的引用存储到volatile字段或AtomicReference中;
- 将对它的引用存储到正确构造的对象的最终字段中; 要么
- 将对它的引用存储到由锁正确保护的字段中.
在其他情况下,您可以(理论上)面对在new构造函数调用完成之前可用于其他线程的结果(由于可能的操作重新排序).
但请注意,如果0是默认值而不是构造函数中写入的值,则保证它是可见的(JLS§17.4.4):
- 向每个变量写入默认值(零,false或null)与每个线程中的第一个操作同步.虽然在分配包含变量的对象之前将默认值写入变量似乎有点奇怪,但概念上每个对象都是在程序开始时使用其默认初始值创建的