字段锁定 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
的新值。我想避免这种情况。
如果我在更新 a
和 b
值之前输入 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() {
...
}
这将使您的代码线程安全:a
和 b
将始终使用相同的 increaseVal
进行更新。
但是,读取 a
和 b
的代码可能仍然读取 a
和 b
而另一个线程是 运行ning updateAB()
等等不保证客户端代码将使用由相同 increaseVal
更新的 a
和 b
:如果这是您需要的,您还必须同步对 [=16= 的访问] 和 b
(但是你的示例中没有显示代码,所以我不能说太多)。
关于updateAB()
的同步:如果方法中有很多代码没有使用a
、b
和increaseVal
,可能花费很长时间 运行(例如,由于 I/O 操作,如数据库访问),那么只同步使用 a
、b
和 [=18 的代码是有意义的=] 而不是整个方法:
private void updateAB() {
...
synchronized(this) {
// Computing the new a and b values
a = ... * increaseVal;
b = ... * increaseVal;
}
...
}
我正在使用以下代码:
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
的新值。我想避免这种情况。
如果我在更新 a
和 b
值之前输入 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() {
...
}
这将使您的代码线程安全:a
和 b
将始终使用相同的 increaseVal
进行更新。
但是,读取 a
和 b
的代码可能仍然读取 a
和 b
而另一个线程是 运行ning updateAB()
等等不保证客户端代码将使用由相同 increaseVal
更新的 a
和 b
:如果这是您需要的,您还必须同步对 [=16= 的访问] 和 b
(但是你的示例中没有显示代码,所以我不能说太多)。
关于updateAB()
的同步:如果方法中有很多代码没有使用a
、b
和increaseVal
,可能花费很长时间 运行(例如,由于 I/O 操作,如数据库访问),那么只同步使用 a
、b
和 [=18 的代码是有意义的=] 而不是整个方法:
private void updateAB() {
...
synchronized(this) {
// Computing the new a and b values
a = ... * increaseVal;
b = ... * increaseVal;
}
...
}