java – 以同步方法读取值时的安全发布
|
我的问题涉及到 Java中字段值的安全发布(如这里所述) 据我所知,一个字段可以安全地读取(意味着从多个线程访问将看到正确的值)如果: >读写在同一个显示器上同步 如果我的理解正确,以下类不应该是线程安全的,因为初始值没有这些特征.然而,我发现很难相信,即使只能从同步方法访问,我也需要使第一个易失性. public class Foo {
private boolean needsGreeting = true;
public synchronized void greet() {
if (needsGreeting) {
System.out.println("hello");
needsGreeting = false;
}
}
}
我错过了什么吗?以上代码是否正确,如果是,为什么?或者在这种情况下,必须先创建volatile或者使用最终的AtomicBoolean或类似的东西,以及从synchronized方法访问它. (只是为了澄清,我知道,如果初始值是用一个synchronized方法编写的,即使没有volatile关键字,它也是线程安全的.) 解决方法在构造函数和方法调用的结尾之间没有发生之前的关系,因此一个线程可能开始构建实例并使引用可用,另一个线程可以获取该引用并开始调用greet( )方法. greet()中的同步并不能解决这个问题.如果您通过着名的双重检查锁定模式发布实例,将变得更容易看到如何.如果有这样的发生关系,即使使用DCLP也应该是安全的. public class Foo {
private boolean needsGreeting = true;
public synchronized void greet() {
if (needsGreeting) {
System.out.println("Hello.");
needsGreeting = false;
}
}
}
class FooUser {
private static Foo foo;
public static Foo getFoo() {
if (foo == null) {
synchronized (FooUser.class) {
if (foo == null) {
foo = new Foo();
}
}
}
return foo;
}
}
如果多个线程同时调用FooUser.getFoo().greet(),一个线程可能正在构造Foo实例,但是另一个线程可能会提前找到一个非空的Foo引用,并调用greet()并发现needGreeting仍然是假. Java并发实践中提到了一个例子(3.5). (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
