我必须同步线程之间对共享对象的访问,该共享对象的状态由多个字段组成。说:
class Shared{
String a; Integer b;
//constructor, getters and setters
....
}
我可能有很多线程读取这个对象,做
//readers
shared.getA();
shared.getB();
并且只有一个线程会在某一点写入:
//writer
shared.setA("state");
shared.setB(1);
现在我的问题是如何确保读取线程不会找到处于不一致状态的共享对象。
我读了很多答案说为了线程之间的一致性 volatile
是解决方案,但我不确定它在多个领域是如何工作的。例如,够了吗?
volatile String a; volatile Integer b;
另一种解决方案是使共享对象不可变并使用 AtomicReference,例如,
AtomicReference<Shared> shared = ....
然后作者将交换引用:
Shared prev = shared.get();
Shared newValue = new Shared("state",1);
while (!shared.compareAndSet(prev, newValue))
这种方法正确吗?谢谢!
更新 在我的设置中,共享对象是从 ConcurrentHashMap<Id,Shared>
中检索的,所以评论一致认为要走的路要么使用不可变方法,要么通过同步所有共享的更新。但是,为了完整起见,很高兴知道上面的解决方案是否带有 ConcurrentHashMap<Id,AtomicReference<Shared>>
是可行的或错误的或只是多余的。谁能解释一下?谢谢!
最佳答案
首先你应该使 Shared
不可变:
class Shared{
private final String a;
private final int b;
//constructor, getters and NO setters
}
如果您只有一个编写器,您可以安全地使用 volatile,在 AtomicReference 中则没有必要。在更新信息时,不应修改旧对象,而应创建新对象并将其分配给 volatile 引用。
关于java - 多个字段 : volatile or AtomicReference?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21283293/