我知道static
synchronized
方法锁定在class
对象上,而实例synchronized
方法锁定在对象的当前实例上,即 this
.
由于这两个对象是不同的,它们有不同的锁,所以当一个线程执行static
synchronized
方法时,java中的另一个线程不需要等待该线程返回,而是它将获得单独的锁。
考虑以下示例
public class Test {
static int count = 0;
public synchronized void f1(){
count++;
}
public static synchronized void f2(){
count++;
}
}
此处的共享计数不是以相互互斥的方式访问的,这可能会导致在另一个线程使用static
f2()
方法递增count
时,将不正确的count
传递给f1()
的调用方。
这种情况的解决方案是什么?我问的问题是否正确,如果不是,请让我正确?如果这是一个真实的情况,那么java pr避免了什么解决方案?
您可以在非静态方法上使用同步块,它应使用与静态同步方法相同的监视器:
public void f1() {
synchronized(Test.class) {
count++;
}
}
经验法则是,静态同步方法应仅用于保护静态变量,而非静态同步方法应仅用于保护非静态变量。
由于count
是静态的,因此从具有非静态同步的块修改它是不正确的。要正确编码并避免代码重复,请从f1
调用f2
,如下所示:
public void f1(){
... // Do something ...
f2();
... // Do something else ...
}
public static synchronized void f2(){
count++;
}