字段锁定 Java

Field lock Java

我正在使用以下代码:

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);
        ...
    }
}

是否可以在 SomeClass updateAB 方法中以某种方式锁定 increaseVal,以便在处理时使用相同的 increaseVal 值,同时 [=17] =] 和 b 字段已更新?

使用当前代码,如果调用 OtherClass 中的 setIncreaseValue,它可能会在 a 更新后更改 increaseVal 的值。以这种方式,更新 b 时将使用 increaseVal 的新值。我想避免这种情况。

如果我在更新 ab 值之前输入 synchronized(this) 会有效吗?

像这样:

synchronized(this) {
    // Computing the new a and b values
    a = ... * increaseVal;
    b = ... * increaseVal;
} 

谢谢!

如果您关心 increaseVal,您可能想要锁定 increaseVal。 即

synchronized(increaseVal) {
    // Computing the new a and b values
    a = ... * increaseVal;
    b = ... * increaseVal;
} 

increaseVal 设为 AtomicInteger。使其成为原子将解决您的问题。

为了正确实现线程安全代码,您必须首先确定 class 中需要使其成为线程安全的状态。 在您的示例中,状态由三个字段表示

private double a;
private double b;
private double increaseVal;

下一步是使用 same 锁确保 all(即读取和写入)对状态的访问是同步的对象。

在您的示例中,使用 this 作为锁,然后将 synchronized 关键字添加到 setIncreaseVal(...)updateAB() 方法可以轻松实现:

public synchronized void setIncreaseVal(double increaseVal) {
    ...
}

private synchronized void updateAB() {
    ...
}

这将使您的代码线程安全:ab 将始终使用相同的 increaseVal 进行更新。 但是,读取 ab 的代码可能仍然读取 ab 而另一个线程是 运行ning updateAB() 等等不保证客户端代码将使用由相同 increaseVal 更新的 ab:如果这是您需要的,您还必须同步对 [=16= 的访问] 和 b (但是你的示例中没有显示代码,所以我不能说太多)。

关于updateAB()的同步:如果方法中有很多代码没有使用abincreaseVal,可能花费很长时间 运行(例如,由于 I/O 操作,如数据库访问),那么只同步使用 ab 和 [=18 的代码是有意义的=] 而不是整个方法:

private void updateAB() {
    ...
    synchronized(this) {
        // Computing the new a and b values
        a = ... * increaseVal;
        b = ... * increaseVal;
    }
    ...
}