pcj*_*zer 8 java immutability thread-safety
它应该是有目的不可变的java类'final'的所有字段,包括超级字段,以便是线程安全的,还是没有修饰符方法?
假设我有一个非最终字段的POJO,其中所有字段都是某些不可变类的类型.这个POJO有getter-setters,以及一个构造函数,它设置了一些初始值.如果我使用敲除修饰符方法扩展此POJO,从而使其不可变,扩展类是否是线程安全的?
axt*_*avt 14
为了final在线程安全的方式中使用没有字段的有效不可变对象,在初始化后使对象可用于其他线程时需要使用安全发布惯用法之一,否则这些线程可以看到处于部分初始化状态的对象(来自Java Concurrency)在实践中):
- 从静态初始化程序初始化对象引用;
- 将对它的引用存储到volatile字段或AtomicReference中;
- 将对它的引用存储到正确构造的对象的最终字段中; 要么
- 将对它的引用存储到由锁正确保护的字段中.
声明不可变对象的字段final释放此限制(即,它保证如果其他线程看到对该对象的引用,它们也会看到其final字段处于完全初始化状态).但是,在一般情况下,它不保证其他线程一旦发布就可以看到对该对象的引用,因此您可能仍需要使用安全发布来确保它.
请注意,如果您的对象实现了一个接口,您可以使用Collections.unmodifiableList()等等使用的方法:
class ImmutableFooWrapper implements IFoo {
private final IFoo delegate; // final provides safe publication automatically
public ImmutableFooWrapper(IFoo delegate) {
this.delegate = delegate;
}
...
}
public IFoo immutableFoo(IFoo foo) {
return new ImmutableFooWrapper(foo);
}
Run Code Online (Sandbox Code Playgroud)