【发布时间】:2014-02-12 12:46:42
【问题描述】:
我必须将线程之间的访问同步到一个共享对象,该对象的状态由几个字段组成。说:
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> 检索的,因此 cmets 同意要走的路是使用不可变方法或通过将共享上的更新同步在一起。但是,为了完整起见,很高兴知道上面使用 ConcurrentHashMap<Id,AtomicReference<Shared>> 的解决方案是可行的、错误的还是多余的。谁能解释一下?谢谢!
【问题讨论】:
-
如果你必须原子地写入a和b,那么解决方案确实是使用不可变的方法。你不需要 AtomicReference,只需要一个简单的 volatile 字段到你当前的 Shared 实例。
-
如果您使
Shared类不可变并且您只有一个线程编写,那么您不需要原子compareAndSet,只需volatile Shared shared;就可以完成这项工作。 -
用ReadWriteLock怎么样?
-
我看到了 volatile 的意义,但是如果我没有这样的引用但我从 map
检索共享对象怎么办?我如何在这里使用易失性?我应该将 map > 与不可变的方法一起使用吗?
标签: java multithreading concurrency atomic atomicreference