当我在实例方法上使用synchronized方法时,监视器与'this'相关联。另一方面,当我在我的类(静态)方法上进行同步时,监视器与类对象相关联。当我在非静态方法中使用静态变量时会发生什么?会同步吗?
例如,
public class A{
public static int reg_no = 100;
public synchronized void registration(){
A.reg_no = some operation...
}
}
在上面的例子中,如果两个或多个线程竞争方法reg_no
,静态变量registration()
会发生什么?
答案 0 :(得分:4)
使用synchronized
注释成员函数时,该方法将在对象的实例上同步。如果要在静态变量上进行同步,则必须手动同步类对象:
public synchronized void registration() {
synchronized (A.class) {
A.reg_no = some operation ...
}
}
请注意,上面获得了两个锁,如果任何其他代码在另一个顺序中获得相同的两个锁,则可以导致deadlocks。您可能希望从方法中删除synchronized
,只留下synchronized (A.class)
。
答案 1 :(得分:1)
不同步对变量(静态或实例)的访问。无论变量(静态或实例)
,该方法的同步都将防止单个实例的竞争条件如果你想要防范多个实例,你必须在类文字上进行同步,但这看起来确实是错误的。
答案 2 :(得分:1)
(经过进一步思考后修改)
对于上面给出的示例,您可以通过声明您的静态int像punkers建议的那样挥发。
在一般情况下 - 例如,如果您的静态变量是具有可变状态的对象......
synchronized实例方法意味着只允许持有对象实例锁的线程在该类A实例的该方法中进行,并且当该线程在该方法中完成并释放锁时,任何其他线程进入任何其他线程使用相同锁定的同步块将“看到”您所做的更改。
不阻止另一个线程对静态变量进行更改:
使用synchronized方法通常有点危险 - 它们可能导致死锁,因为锁可以被其他代码使用,这些代码使用您的类/实例作为同步块的目标:
synchronized (objectOfTypeA) { ... } // takes the instance lock
或
synchronized (A.getClass()) { ... } // takes the class lock
更好的方法可能是将静态变量设为私有,添加一个私有局部变量用作锁(因此无法在外部锁定),并在方法中的synchronized块中使用私有本地锁:
public class A {
private static int reg_no = 100;
private static Object lock = new Object();
public void registration(){
synchronized(lock) {
reg_no = some operation...
}
}
public static int getRegNo() {
synchronized(lock) {
return reg_no;
}
}
}
答案 3 :(得分:0)
不,您需要将方法同步到类,例如。 synchronized(A.class)
。
答案 4 :(得分:0)
而不是在synchronized方法中添加另一个synchronized块我会将静态变量声明为volatile,如果你的问题是与其他线程共享该变量。