我使用以下代码:
public class SomeClass extends Thread {
...
private double a;
private double b;
private double increaseVal;
public void setIncreaseVal(double increaseVal) {
this.increaseVal = increaseVal;
}
private void updateAB() {
...
// Computing the new a and b values
a = ... * increaseVal;
b = ... * increaseVal;
...
}
@Override
public void run() {
try {
...
updateAB();
Thread.sleep(500);
}
...
}
}
public class OtherClass {
...
private HashMap<String, SomeClass> someClasses;
private void setIncreaseValue( String id, double value){
...
someClasses.get(id).setIncreaseValue(value);
...
}
}
是否可以以某种方式锁定increaseVal
SomeClass
方法中的updateAB
,以便在处理时increaseVal
同时使用a
值b
和setIncreaseValue
字段已更新?
如果调用来自OtherClass
的{{1}},则使用当前代码,可以在increaseVal
更新后更改a
的值。通过这种方式,increaseVal
更新时将使用b
的新值。我想避免这种情况。
如果我在更新synchronized(this)
和a
值之前添加b
会有效吗?
像这样:
synchronized(this) {
// Computing the new a and b values
a = ... * increaseVal;
b = ... * increaseVal;
}
谢谢!
答案 0 :(得分:0)
如果您关注的是increaseVal,则可能需要锁定increaseVal。 即
synchronized(increaseVal) {
// Computing the new a and b values
a = ... * increaseVal;
b = ... * increaseVal;
}
答案 1 :(得分:0)
将increaseVal
设为AtomicInteger。使其成为原子将解决您的问题。
答案 2 :(得分:0)
为了正确实现线程安全代码,您必须首先确定类中需要使线程安全的状态。 在您的示例中,状态由三个字段
表示private double a;
private double b;
private double increaseVal;
下一步是确保使用相同锁定对象同步所有(即读取和写入)对状态的访问。
在您的示例中,可以使用this
作为锁定轻松实现,然后将synchronized关键字添加到setIncreaseVal(...)
和updateAB()
方法:
public synchronized void setIncreaseVal(double increaseVal) {
...
}
private synchronized void updateAB() {
...
}
这将使您的代码线程安全:a
和b
将始终使用相同的increaseVal
进行更新。
但是,当另一个线程正在运行a
时,读取b
和a
的代码仍可能会读取b
和updateAB()
,因此无法保证客户端代码将使用a
和b
由同一increaseVal
更新:如果这是您需要的,您还必须同步a
和{{1}的访问权限(但是代码没有显示在你的例子中,所以我不能对它说太多)。
关于b
的同步:如果方法中有很多代码没有使用updateAB()
,a
和b
,可能会需要很长时间才能运行(例如,由于I / O操作,如数据库访问),那么只同步使用increaseVal
,a
和b
的代码而不是整个代码是有意义的方法:
increaseVal