假设我有这段 Java 代码
我想知道是否有一种无锁机制可以使突出显示的代码片段成为原子的。我想避免当有人调用 fetchSomeThing()
时,我正处于 BlockX
的中间,并且 fetchSomeThing()
正在从新的副本中查找A 但 B 和 C 的旧副本。
public class MyClass
{
private volatile Map a, b, c;
public void refresh()
{
Map a_ = loadA();
Map b_ = loadB();
Map c_ = loadC();
//I want to make the following block atomic
// call it Block X
{
this.a = a_;
this.b = b_;
this.c = c_;
}
}
public String fetchSomeThing()
{
// some joint operations on this.a, this.b and this.c
}
}
我能想到的唯一方法是将其分成两个类并将 a、b、c 包装在一个对象中。
但是非常麻烦。有没有更好的办法?
public class MyShadowClass
{
private Map a, b, c;
public MyShadowClass()
{
init();
}
public void init()
{
Map a_ = loadA();
Map b_ = loadB();
Map c_ = loadC();
this.a = a_;
this.b = b_;
this.c = c_;
}
public String fetchSomeThing()
{
// some joint operations on this.a, this.b and this.c
}
}
public class MyClass
{
private volatile MyShadowClass shadow;
public void refresh()
{
MyShadowClass tempShadow = new MyShadowClass();
shadow = tempShadow;
}
public String fetchSomeThing()
{
return shadow.fetchSomeThing();
}
}
最佳答案
简单地创建一个保持当前有效状态的复合对象。然后,您可以使用 AtomicReference 来管理当前状态:
private AtomicReference<Thing> currentThing = new AtomicReference<Thing>();
public Thing getThing() {
while (true) {
Thing result = currentThing.get();
if (result != null)
return result;
result = buildThing();
if (currentThing.compareAndSet(null, result);
return result;
}
}
private Thing buildThing() {
// whatever, only important thing is that this creates
// a new and valid instance of Thing
}
public void refresh() {
Thing freshThing = buildThing();
currentThing.set(freshThing);
}
如果您可以确保只有一个线程写入该字段,或者您不特别关心在刷新()和初始时获取相同的实例,那么您可以简单地将“currentThing”声明为正常的但 volatile 字段。 get 正在同时执行。
关于Java:使代码块原子化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26633957/