在java中的synchronized方法或块中使用静态成员

时间:2010-10-12 09:10:53

标签: java multithreading

当我在实例方法上使用synchronized方法时,监视器与'this'相关联。另一方面,当我在我的类(静态)方法上进行同步时,监视器与类对象相关联。当我在非静态方法中使用静态变量时会发生什么?会同步吗?

例如,

public class A{

   public static int reg_no = 100;

   public synchronized void registration(){

      A.reg_no = some operation...

   }

}

在上面的例子中,如果两个或多个线程竞争方法reg_no,静态变量registration()会发生什么?

5 个答案:

答案 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实例的该方法中进行,并且当该线程在该方法中完成并释放锁时,任何其他线程进入任何其他线程使用相同锁定的同步块将“看到”您所做的更改。

阻止另一个线程对静态变量进行更改:

  • 直接从外部类A(变量为public!)
  • 为静态变量赋值
  • 调用类A的静态方法(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,如果你的问题是与其他线程共享该变量。