Joe*_*e23 11 java multithreading thread-safety
我的问题涉及在Java中安全发布字段值(这里讨论Java多线程和安全发布).
据我了解,如果出现以下情况,可以安全地读取字段(意味着从多个线程访问将看到正确的值):
如果我的理解是正确的,那么下面的类不应该是线程安全的,因为初始值是在没有这些特性的情况下编写的.但是我觉得很难相信我需要制作,first volatile即使它只是从一个synchronized方法访问.
public class Foo {
private boolean needsGreeting = true;
public synchronized void greet() {
if (needsGreeting) {
System.out.println("hello");
needsGreeting = false;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我错过了什么吗?以上代码是否正确,如果是,为什么?或者在这种情况下,除了从方法访问它之外,还需要制作first volatile或使用final 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;
}
}
Run Code Online (Sandbox Code Playgroud)
如果多个线程同时调用FooUser.getFoo().greet(),则一个线程可能正在构造Foo实例,但另一个线程可能过早地找到非空Foo引用,并调用greet()并查找needsGreeting仍然是假.
Java Concurrency in Practice(3.5)中提到了一个这样的例子.
| 归档时间: |
|
| 查看次数: |
354 次 |
| 最近记录: |