场锁Java

时间:2016-10-13 11:23:49

标签: java multithreading locking synchronized

我使用以下代码:

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同时使用absetIncreaseValue字段已更新?

如果调用来自OtherClass的{​​{1}},则使用当前代码,可以在increaseVal更新后更改a的值。通过这种方式,increaseVal更新时将使用b的新值。我想避免这种情况。

如果我在更新synchronized(this)a值之前添加b会有效吗?

像这样:

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

谢谢!

3 个答案:

答案 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() {
    ...
}

这将使您的代码线程安全:ab将始终使用相同的increaseVal进行更新。 但是,当另一个线程正在运行a时,读取ba的代码仍可能会读取bupdateAB(),因此无法保证客户端代码将使用ab由同一increaseVal更新:如果这是您需要的,您还必须同步a和{{1}的访问权限(但是代码没有显示在你的例子中,所以我不能对它说太多)。

关于b的同步:如果方法中有很多代码没有使用updateAB()ab,可能会需要很长时间才能运行(例如,由于I / O操作,如数据库访问),那么只同步使用increaseValab的代码而不是整个代码是有意义的方法:

increaseVal