Java规范17.5具有下面的代码来说明使用最终字段在Java存储模型的。 (相比于普通字段)这不是用Java解释Final的一个坏例子吗?
class FinalFieldExample {
final int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}
static void reader() {
if (f != null) {
int i = f.x; // guaranteed to see 3
int j = f.y; // could see 0
}
}
}
该规范接着说:
“类FinalFieldExample有一个最终诠释现场x和非最终诠释字段,Y的 一个线程可以执行。由于writer方法在对象的构造器完成后写入f,读者方法将保证看到fx的正确初始化值:它将读取值3. 但是,fy是不是最终的;读者的方法因此不能保证看到它的价值4。“
我的问题是:这不是一个跛脚(或至少是一个非常做作)的例子吗? 还是我失去了一些东西?
我的推理项的实例为“跛”是:
如果FinalFieldExample类的对象要被通过螺纹在一个多线程的情况下共享,不应该它遵循多线程的基本原则,这是使用某种形式的同步。如果他们使用过同步,那么提到的问题将不存在。
上述例子似乎主张最终字段作为适当的同步技术的替代(或部分橡皮奶头)。根据我的理解,即使在正确的同步之上使用最终字段也是有用的。并且不应该被用来获得示例中提到的优势(在没有同步的情况下)。
所以人们可能要问: 是不是有一个体面的例子(同步于)解释过正常的域最终场的优势在哪里?我猜,不可变性是!
它就是当前内存模型下最终字段发生情况的一个例子。这不是主张你写这样的代码。请参阅JCIP以获取有关如何编写并发代码的建议,其中基本原则是“尽可能使用更高级别的构造(在java.util.concurrent中)”。 –
@NathanHughes:您的评论非常有趣。你能否在JCIP中提供一个参考文件(在使用更高层次的结构时)?谢谢 ! – brainOverflow
尝试JCIP的这句话,第5章开始:“在实际情况下,委派是创建线程安全类最有效的策略之一:让现有线程安全类管理所有状态。” –